##// 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
The requested commit or file is too big and content was truncated. Show full diff
1 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
The requested commit or file is too big and content was truncated. Show full diff
1 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
The requested commit or file is too big and content was truncated. Show full diff
1 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
The requested commit or file is too big and content was truncated. Show full diff
1 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
The requested commit or file is too big and content was truncated. Show full diff
1 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 1 [bumpversion]
2 current_version = 4.15.2
2 current_version = 4.16.0
3 3 message = release: Bump version {current_version} to {new_version}
4 4
5 5 [bumpversion:file:rhodecode/VERSION]
@@ -5,25 +5,20 b' done = false'
5 5 done = true
6 6
7 7 [task:rc_tools_pinned]
8 done = true
9 8
10 9 [task:fixes_on_stable]
11 done = true
12 10
13 11 [task:pip2nix_generated]
14 done = true
15 12
16 13 [task:changelog_updated]
17 done = true
18 14
19 15 [task:generate_api_docs]
20 done = true
16
17 [task:updated_translation]
21 18
22 19 [release]
23 state = prepared
24 version = 4.15.2
25
26 [task:updated_translation]
20 state = in_progress
21 version = 4.16.0
27 22
28 23 [task:generate_js_routes]
29 24
@@ -12,8 +12,6 b' permission notice:'
12 12 file:licenses/msgpack_license.txt
13 13 Copyright (c) 2009 - tornado
14 14 file:licenses/tornado_license.txt
15 Copyright (c) 2015 - pygments-markdown-lexer
16 file:licenses/pygments_markdown_lexer_license.txt
17 15 Copyright 2006 - diff_match_patch
18 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 4 NODE_PATH=./node_modules
5 5 WEBPACK=./node_binaries/webpack
@@ -8,7 +8,7 b' GRUNT=./node_binaries/grunt'
8 8
9 9 clean:
10 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 13 test:
14 14 make test-clean
@@ -51,3 +51,5 b' docs-cleanup:'
51 51 web-build:
52 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 53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
54 54
55 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 57 ## RhodeCode can handle at the same time. Each additional worker also it increases
58 58 ## memory usage as each has it's own set of caches.
59 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 133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
134 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 137 gzip_responses = false
138 138
139 ## autogenerate javascript routes file on startup
139 ## auto-generate javascript routes file on startup
140 140 generate_js_files = false
141 141
142 142 ## System global default language.
@@ -153,7 +153,7 b' startup.import_repos = false'
153 153 ## the repository.
154 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 157 ## requests in context when no web request is available. Used in ishell, or
158 158 ## SSH calls. Set this for events to receive proper url for SSH calls.
159 159 app.base_url = http://rhodecode.local
@@ -203,7 +203,7 b' gist_alias_url ='
203 203 ## used for access.
204 204 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
205 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 207 ## authentication token. Such view would be only accessible when used together
208 208 ## with this authentication token
209 209 ##
@@ -227,14 +227,14 b' default_encoding = UTF-8'
227 227
228 228 ## instance-id prefix
229 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
231 ## all running rhodecode instances. Leave empty if you don't use it
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
232 232 instance_id =
233 233
234 234 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
235 235 ## of an authentication plugin also if it is disabled by it's settings.
236 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 238 ## module to log in again and fix the settings.
239 239 ##
240 240 ## Available builtin plugin IDs (hash is part of the ID):
@@ -250,7 +250,7 b' instance_id ='
250 250 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
251 251 ## handling that causing a series of failed authentication calls.
252 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 254 auth_ret_code =
255 255
256 256 ## use special detection method when serving auth_ret_code, instead of serving
@@ -284,6 +284,13 b' labs_settings_active = true'
284 284 ## This is used to store exception from RhodeCode in shared directory
285 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 296 ### CELERY CONFIG ####
@@ -325,6 +332,7 b' rc_cache.cache_perms.expiration_time = 3'
325 332 #rc_cache.cache_perms.arguments.host = localhost
326 333 #rc_cache.cache_perms.arguments.port = 6379
327 334 #rc_cache.cache_perms.arguments.db = 0
335 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
328 336 #rc_cache.cache_perms.arguments.distributed_lock = true
329 337
330 338 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
@@ -340,6 +348,7 b' rc_cache.cache_repo.expiration_time = 25'
340 348 #rc_cache.cache_repo.arguments.host = localhost
341 349 #rc_cache.cache_repo.arguments.port = 6379
342 350 #rc_cache.cache_repo.arguments.db = 1
351 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
343 352 #rc_cache.cache_repo.arguments.distributed_lock = true
344 353
345 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 433 ## location of the channelstream server from outside world
425 434 ## use ws:// for http or wss:// for https. This address needs to be handled
426 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 437 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
429 438 channelstream.secret = secret
430 439 channelstream.history.location = %(here)s/channelstream_history
@@ -441,14 +450,14 b' channelstream.proxy_path = /_channelstre'
441 450 ## Appenlight is tailored to work with RhodeCode, see
442 451 ## http://appenlight.com for details how to obtain an account
443 452
444 ## appenlight integration enabled
453 ## Appenlight integration enabled
445 454 appenlight = false
446 455
447 456 appenlight.server_url = https://api.appenlight.com
448 457 appenlight.api_key = YOUR_API_KEY
449 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 461 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
453 462
454 463 ## TWEAK AMOUNT OF INFO SENT HERE
@@ -473,7 +482,7 b' appenlight.logging.level = WARNING'
473 482 ## (saves API quota for intensive logging)
474 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 486 ## can be string with comma separated list of words in lowercase
478 487 ## (by default client will always send following info:
479 488 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
@@ -533,7 +542,7 b' sqlalchemy.db1.convert_unicode = true'
533 542 vcs.server.enable = true
534 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 546 ## Available protocols are:
538 547 ## `http` - use http-rpc backend (default)
539 548 vcs.server.protocol = http
@@ -582,7 +591,8 b' svn.proxy.config_file_path = %(here)s/mo'
582 591 ## In most cases it should be set to `/`.
583 592 svn.proxy.location_root = /
584 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 596 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
587 597 ## If the timeout expires before the reload command finishes, the command will
588 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 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 607 ## of adding SSH keys by users from web interface. Super admins can still
598 608 ## manage SSH Keys.
599 609 ssh.generate_authorized_keyfile = false
@@ -601,13 +611,13 b' ssh.generate_authorized_keyfile = false'
601 611 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
602 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 615 ## It is possible to have multiple key files specified in `sshd_config` e.g.
606 616 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
607 617 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
608 618
609 619 ## Command to execute the SSH wrapper. The binary is available in the
610 ## rhodecode installation directory.
620 ## RhodeCode installation directory.
611 621 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
612 622 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
613 623
@@ -615,7 +625,7 b' ssh.wrapper_cmd = ~/.rccontrol/community'
615 625 ssh.wrapper_cmd_allow_shell = false
616 626
617 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 629 ssh.enable_debug_logging = true
620 630
621 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 634 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
625 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 642 ## Dummy marker to add new entries after.
629 643 ## Add any custom entries below. Please don't remove.
@@ -53,7 +53,7 b' port = 5000'
53 53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
54 54
55 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 57 ## RhodeCode can handle at the same time. Each additional worker also it increases
58 58 ## memory usage as each has it's own set of caches.
59 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 108 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
109 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 112 gzip_responses = false
113 113
114 ## autogenerate javascript routes file on startup
114 ## auto-generate javascript routes file on startup
115 115 generate_js_files = false
116 116
117 117 ## System global default language.
@@ -128,7 +128,7 b' startup.import_repos = false'
128 128 ## the repository.
129 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 132 ## requests in context when no web request is available. Used in ishell, or
133 133 ## SSH calls. Set this for events to receive proper url for SSH calls.
134 134 app.base_url = http://rhodecode.local
@@ -178,7 +178,7 b' gist_alias_url ='
178 178 ## used for access.
179 179 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
180 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 182 ## authentication token. Such view would be only accessible when used together
183 183 ## with this authentication token
184 184 ##
@@ -202,14 +202,14 b' default_encoding = UTF-8'
202 202
203 203 ## instance-id prefix
204 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
206 ## all running rhodecode instances. Leave empty if you don't use it
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
207 207 instance_id =
208 208
209 209 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
210 210 ## of an authentication plugin also if it is disabled by it's settings.
211 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 213 ## module to log in again and fix the settings.
214 214 ##
215 215 ## Available builtin plugin IDs (hash is part of the ID):
@@ -225,7 +225,7 b' instance_id ='
225 225 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
226 226 ## handling that causing a series of failed authentication calls.
227 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 229 auth_ret_code =
230 230
231 231 ## use special detection method when serving auth_ret_code, instead of serving
@@ -259,6 +259,13 b' labs_settings_active = true'
259 259 ## This is used to store exception from RhodeCode in shared directory
260 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 271 ### CELERY CONFIG ####
@@ -300,6 +307,7 b' rc_cache.cache_perms.expiration_time = 3'
300 307 #rc_cache.cache_perms.arguments.host = localhost
301 308 #rc_cache.cache_perms.arguments.port = 6379
302 309 #rc_cache.cache_perms.arguments.db = 0
310 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
303 311 #rc_cache.cache_perms.arguments.distributed_lock = true
304 312
305 313 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
@@ -315,6 +323,7 b' rc_cache.cache_repo.expiration_time = 25'
315 323 #rc_cache.cache_repo.arguments.host = localhost
316 324 #rc_cache.cache_repo.arguments.port = 6379
317 325 #rc_cache.cache_repo.arguments.db = 1
326 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
318 327 #rc_cache.cache_repo.arguments.distributed_lock = true
319 328
320 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 408 ## location of the channelstream server from outside world
400 409 ## use ws:// for http or wss:// for https. This address needs to be handled
401 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 412 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
404 413 channelstream.secret = secret
405 414 channelstream.history.location = %(here)s/channelstream_history
@@ -416,14 +425,14 b' channelstream.proxy_path = /_channelstre'
416 425 ## Appenlight is tailored to work with RhodeCode, see
417 426 ## http://appenlight.com for details how to obtain an account
418 427
419 ## appenlight integration enabled
428 ## Appenlight integration enabled
420 429 appenlight = false
421 430
422 431 appenlight.server_url = https://api.appenlight.com
423 432 appenlight.api_key = YOUR_API_KEY
424 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 436 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
428 437
429 438 ## TWEAK AMOUNT OF INFO SENT HERE
@@ -448,7 +457,7 b' appenlight.logging.level = WARNING'
448 457 ## (saves API quota for intensive logging)
449 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 461 ## can be string with comma separated list of words in lowercase
453 462 ## (by default client will always send following info:
454 463 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
@@ -506,7 +515,7 b' sqlalchemy.db1.convert_unicode = true'
506 515 vcs.server.enable = true
507 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 519 ## Available protocols are:
511 520 ## `http` - use http-rpc backend (default)
512 521 vcs.server.protocol = http
@@ -555,7 +564,8 b' svn.proxy.config_file_path = %(here)s/mo'
555 564 ## In most cases it should be set to `/`.
556 565 svn.proxy.location_root = /
557 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 569 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
560 570 ## If the timeout expires before the reload command finishes, the command will
561 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 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 580 ## of adding SSH keys by users from web interface. Super admins can still
571 581 ## manage SSH Keys.
572 582 ssh.generate_authorized_keyfile = false
@@ -574,13 +584,13 b' ssh.generate_authorized_keyfile = false'
574 584 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
575 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 588 ## It is possible to have multiple key files specified in `sshd_config` e.g.
579 589 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
580 590 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
581 591
582 592 ## Command to execute the SSH wrapper. The binary is available in the
583 ## rhodecode installation directory.
593 ## RhodeCode installation directory.
584 594 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
585 595 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
586 596
@@ -588,7 +598,7 b' ssh.wrapper_cmd = ~/.rccontrol/community'
588 598 ssh.wrapper_cmd_allow_shell = false
589 599
590 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 602 ssh.enable_debug_logging = false
593 603
594 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 607 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
598 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 615 ## Dummy marker to add new entries after.
602 616 ## Add any custom entries below. Please don't remove.
@@ -19,14 +19,15 b''
19 19 # }
20 20
21 21 args@
22 { pythonPackages ? "python27Packages"
22 { system ? builtins.currentSystem
23 , pythonPackages ? "python27Packages"
23 24 , pythonExternalOverrides ? self: super: {}
24 25 , doCheck ? false
25 26 , ...
26 27 }:
27 28
28 29 let
29 pkgs_ = (import <nixpkgs> {});
30 pkgs_ = args.pkgs or (import <nixpkgs> { inherit system; });
30 31 in
31 32
32 33 let
@@ -80,7 +81,8 b' let'
80 81
81 82 nodeEnv = import ./pkgs/node-default.nix {
82 83 inherit
83 pkgs;
84 pkgs
85 system;
84 86 };
85 87 nodeDependencies = nodeEnv.shell.nodeDependencies;
86 88
@@ -116,7 +116,7 b' Full-text Search Backup'
116 116
117 117 You may also have full text search set up, but the index can be rebuild from
118 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 120 the :ref:`indexing-ref` section.
121 121
122 122 Restoration Steps
@@ -140,7 +140,7 b' Post Restoration Steps'
140 140 Once you have restored your |RCE| instance to basic functionality, you can
141 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 144 you had made changes and rerun the indexer. See the
145 145 :ref:`indexing-ref` section for details.
146 146 * To reconfigure any extensions, copy the backed up extensions into the
@@ -23,9 +23,9 b' sections.'
23 23 * :ref:`increase-gunicorn`
24 24 * :ref:`x-frame`
25 25
26 \- **mapping.ini**
26 \- **search_mapping.ini**
27 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 30 This file is used to control the |RCE| indexer. It comes configured
31 31 to index your instance. To change the default configuration, see
@@ -3,35 +3,41 b''
3 3 Full-text Search
4 4 ----------------
5 5
6 By default RhodeCode is configured to use `Whoosh`_ to index |repos| and
7 provide full-text search.
6 RhodeCode provides a full text search capabilities to search inside file content,
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 search. See :ref:`enable-elasticsearch` for details.
10 By default RhodeCode is configured to use `Whoosh`_ to index |repos| and
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 17 Indexing
13 18 ^^^^^^^^
14 19
15 To run the indexer you need to use an |authtoken| with admin rights to all
16 |repos|.
20 To run the indexer you need to have an |authtoken| with admin rights to all |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 23 number of ways, for example:
20 24
21 * Call the indexer via a cron job. We recommend running this nightly,
22 unless you need everything indexed immediately.
23 * Set the indexer to infinitely loop and reindex as soon as it has run its
24 cycle.
25 * Call the indexer via a cron job. We recommend running this once at night.
26 In case you need everything indexed immediately it's possible to index few
27 times during the day. Indexer has a special locking mechanism that won't allow
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 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
28 wish to build a brand new index from scratch each time,
29 use the ``force`` option in the configuration file.
32 The indexer works by indexing new commits added since the last run, and comparing
33 file changes to index only new or modified files.
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 37 .. important::
32 38
33 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 42 To set up indexing, use the following steps:
37 43
@@ -45,6 +51,13 b' 4. :ref:`advanced-indexing`'
45 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 61 |RCT| uses the :file:`/home/{user}/.rhoderc` file for connection details
49 62 to |RCE| instances. If this file is not automatically created,
50 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 72 - NAME: enterprise-1
60 73 - STATUS: RUNNING
61 - TYPE: Momentum
62 - VERSION: 1.5.0
63 - URL: http://127.0.0.1:10000
74 - TYPE: Enterprise
75 - VERSION: 4.1.0
76 - URL: http://127.0.0.1:10003
64 77
65 78 To get your API Token, on the |RCE| interface go to
66 79 :menuselection:`username --> My Account --> Auth tokens`
@@ -72,29 +85,35 b' To get your API Token, on the |RCE| inte'
72 85 [instance:enterprise-1]
73 86 api_host = http://127.0.0.1:10000
74 87 api_key = <auth token goes here>
75 repo_dir = /home/<username>/repos
88
76 89
77 90 .. _run-index:
78 91
79 92 Run the Indexer
80 93 ^^^^^^^^^^^^^^^
81 94
82 Run the indexer using the following command, and specify the instance you
83 want to index:
95 Run the indexer using the following command, and specify the instance you want to index:
84 96
85 97 .. code-block:: bash
86 98
87 # From inside a virtualevv
88 (venv)$ rhodecode-index --instance-name=enterprise-1
89
90 # Using default installation
99 # Using default simples indexing of all repositories
91 100 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
92 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 104 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
96 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 118 .. note::
100 119
@@ -136,119 +155,173 b' 3. Save the file.'
136 155 # using a specially configured mapping file
137 156 */15 * * * * ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
138 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 160 .. _advanced-indexing:
142 161
143 162 Advanced Indexing
144 163 ^^^^^^^^^^^^^^^^^
145 164
146 |RCT| indexes based on the :file:`mapping.ini` file. To configure your index,
147 you can specify different options in this file. The default location is:
165
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
150 |RCT|.
180 The indexer automatically removes renamed repositories and builds index for new names.
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 202 * :file:`~/venv/lib/python2.7/site-packages/rhodecode_tools/templates/mapping.ini`,
152 203 when using ``virtualenv``.
153 204
154 205 .. note::
155 206
156 If you need to create the :file:`mapping.ini` file, use the |RCT|
157 ``rhodecode-index --create-mapping path/to/file`` API call. For details,
158 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.
207 If you need to create the :file:`search_mapping.ini` file manually, use the |RCT|
208 ``rhodecode-index --create-mapping path/to/search_mapping.ini`` API call.
209 For details, see the :ref:`tools-cli` section.
164 210
165 * ``index_files`` : Index the specified file types.
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|.
211 To Run the indexer with mapping file provide it using `--mapping` flag::
178 212
179 At the end of the file you can specify conditions for specific |repos| that
180 will override the default values. To configure your indexer,
181 use the following example :file:`mapping.ini` file.
213 rhodecode-index --instance-name=enterprise-1 --mapping=/my/path/search_mapping.ini
214
215
216 Here's a detailed example of using :file:`search_mapping.ini` file.
182 217
183 218 .. code-block:: ini
184 219
185 220 [__DEFAULT__]
186 # default patterns for indexing files and content of files.
187 # Binary files are skipped by default.
221 ; Create index on commits data, and files data in this order. Available options
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
190 index_files = *.py, *.md
229 ; Commit process limit. Limit the number of commits indexer should fetch, and
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
193 skip_files = *.svg, *.log, *.dump, *.txt
236 ; Limit of how many repositories each run can process, default is -1 (unlimited)
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
196 index_files_content = *.cpp, *.ini, *.py
241 ; Default patterns for indexing files and content of files. Binary files
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
199 skip_files_content = *.svg,
253 ; Add to index content of those comma separated files; globs syntax
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
202 # from scratch with a global flag. Use local flag to rebuild single repos
257 ; Do not add to index content of those comma separated files; globs syntax
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 264 force = false
204 265
205 # Do not index files larger than 385KB
206 max_filesize = 385KB
266 ; maximum file size that indexer will use, files above that limit are not going
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__.
215
216 [__INCLUDE__]
217 # Include all repos with these names
272 [__INDEX_RULES__]
273 ; Ordered match rules for repositories. A list of all repositories will be fetched
274 ; using API and this list will be filtered using those rules.
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
226 legacy-repos/* = 1
227 *-dev/* = 1
228
229 # Each repo that needs special indexing is a separate section below.
230 # In each section set the options to override the global configuration
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
287 ; == EXPLICIT REPOSITORY INDEXING ==
288 ; If defined this will skip using __INDEX_RULES__, and will not use API to fetch
289 ; list of repositories, it will explicitly take names defined with [NAME] format and
290 ; try to build the index, to build index just for repo_name_1 and special-repo use:
291 ; [repo_name_1]
292 ; [special-repo]
235 293
236 # For this repo use different settings
237 [special-repo]
238 commit_parse_limit = 20,
239 skip_files = *.idea, *.xml,
294 ; == PER REPOSITORY CONFIGURATION ==
295 ; This allows overriding the global configuration per repository.
296 ; example to set specific file limit, and skip certain files for repository special-repo
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
242 [another-special-repo]
243 index_files = *,
244 max_filesize = 800MB
245 commit_parse_limit = 20000
303
304 In case of 1000s of repositories it can be tricky to write the include/exclude rules at first.
305 There's a special flag to test the mapping file rules and list repositories that would
306 be indexed. Run the indexer with `--show-matched-repos` to list only the
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 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 325 1. Open the :file:`rhodecode.ini` file for the instance you wish to edit. The
253 326 default location is
254 327 :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
@@ -268,9 +341,19 b' and change it to:'
268 341 .. code-block:: ini
269 342
270 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 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 9 ## Rate limiter for certain pages to prevent brute force attacks
10 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 15 ## Custom log format
13 16 log_format log_custom '$remote_addr - $remote_user [$time_local] '
14 17 '"$request" $status $body_bytes_sent '
@@ -141,6 +144,34 b' Use the following example to configure N'
141 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 175 location / {
145 176 try_files $uri @rhodecode_http;
146 177 }
@@ -35,7 +35,7 b' 2. On the |repo| group settings page you'
35 35
36 36 * :guilabel:`Owner`: Lets you change the group owner. Useful when users are
37 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 39 of a larger group, i.e. :guilabel:`QA-Repos >> QA-Repos-Berlin`
40 40 * :guilabel:`Enable automatic locking`: For more information,
41 41 see :ref:`repo-locking`
@@ -30,3 +30,5 b' The following are the most common system'
30 30 enable-debug
31 31 admin-tricks
32 32 cleanup-cmds
33 restore-deleted-repositories
34
@@ -78,7 +78,7 b' Configuration Files'
78 78 -------------------
79 79
80 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 82 * :file:`/home/{user}/.rccontrol/{vcsserver-id}/vcsserver.ini`
83 83 * :file:`/home/{user}/.rccontrol/supervisor/supervisord.ini`
84 84 * :file:`/home/{user}/.rccontrol.ini`
@@ -196,7 +196,8 b' are not required in args.'
196 196 .. --- API DEFS MARKER ---
197 197 .. toctree::
198 198
199 methods/views
199 methods/repo-methods
200 methods/store-methods
200 201 methods/license-methods
201 202 methods/deprecated-methods
202 203 methods/gist-methods
@@ -83,7 +83,7 b' comment_pull_request'
83 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 88 Creates a new pull request.
89 89
@@ -104,6 +104,8 b' create_pull_request'
104 104 :type source_ref: str
105 105 :param target_ref: Set the target ref name.
106 106 :type target_ref: str
107 :param owner: user_id or username
108 :type owner: Optional(str)
107 109 :param title: Optionally Set the pull request title, it's generated otherwise
108 110 :type title: str
109 111 :param description: Set the pull request description.
@@ -248,7 +250,7 b' get_pull_request_comments'
248 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 255 Get all pull requests from the repository specified in `repoid`.
254 256
@@ -262,6 +264,9 b' get_pull_requests'
262 264 * ``open``
263 265 * ``closed``
264 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 271 Example output:
267 272
@@ -358,6 +363,7 b' merge_pull_request'
358 363 "result": {
359 364 "executed": "<bool>",
360 365 "failure_reason": "<int>",
366 "merge_status_message": "<str>",
361 367 "merge_commit_id": "<merge_commit_id>",
362 368 "possible": "<bool>",
363 369 "merge_ref": {
@@ -394,6 +394,105 b' get_repo_changesets'
394 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 496 get_repo_nodes
398 497 --------------
399 498
@@ -419,8 +518,8 b' get_repo_nodes'
419 518 ``all`` (default), ``files`` and ``dirs``.
420 519 :type ret_type: Optional(str)
421 520 :param details: Returns extended information about nodes, such as
422 md5, binary, and or content. The valid options are ``basic`` and
423 ``full``.
521 md5, binary, and or content.
522 The valid options are ``basic`` and ``full``.
424 523 :type details: Optional(str)
425 524 :param max_file_bytes: Only return file content under this file size bytes
426 525 :type details: Optional(int)
@@ -432,10 +531,17 b' get_repo_nodes'
432 531 id : <id_given_in_input>
433 532 result: [
434 533 {
435 "name" : "<name>"
436 "type" : "<type>",
437 "binary": "<true|false>" (only in extended mode)
438 "md5" : "<md5 of file content>" (only in extended mode)
534 "binary": false,
535 "content": "File line
536 Line2
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 103 :param apiuser: This is filled automatically from the |authtoken|.
104 104 :type apiuser: AuthUser
105 105 :param pattern: pattern to match method names against
106 :type older_then: Optional("*")
106 :type pattern: Optional("*")
107 107
108 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 16 auth-saml-duosecurity
17 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 73 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
74 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 81 3. Set base_url for instance to enable proper event handling (Optional):
78 82
@@ -52,6 +52,7 b' run::'
52 52 Followed by::
53 53
54 54 nix-channel --update
55 nix-env -i nix-2.0.4
55 56
56 57
57 58 Install required binaries
@@ -65,6 +66,18 b' run::'
65 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 81 Clone the required repositories
69 82 -------------------------------
70 83
@@ -76,8 +89,8 b' you have it installed before continuing.'
76 89 To obtain the required sources, use the following commands::
77 90
78 91 mkdir rhodecode-develop && cd rhodecode-develop
79 hg clone https://code.rhodecode.com/rhodecode-enterprise-ce
80 hg clone https://code.rhodecode.com/rhodecode-vcsserver
92 hg clone -u default https://code.rhodecode.com/rhodecode-enterprise-ce
93 hg clone -u default https://code.rhodecode.com/rhodecode-vcsserver
81 94
82 95 .. note::
83 96
@@ -93,11 +106,15 b' need to install the following.'
93 106
94 107 required libraries::
95 108
109 # svn related
96 110 sudo apt-get install libapr1-dev libaprutil1-dev
97 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 115 sudo apt-get install mysql-server libmysqlclient-dev
99 116 sudo apt-get install postgresql postgresql-contrib libpq-dev
100 sudo apt-get install libcurl4-openssl-dev
117
101 118
102 119
103 120 Enter the Development Shell
@@ -182,7 +199,7 b" To use the application's frontend and pr"
182 199 you will need to compile the CSS and JavaScript with Grunt.
183 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 204 When developing new features you will need to recompile following any
188 205 changes made to the CSS or JavaScript files when developing the code::
@@ -18,11 +18,11 b' Activating rcextensions'
18 18 To activate rcextensions simply copy or rename the created template rcextensions
19 19 into the path where the rhodecode.ini file is located::
20 20
21 pushd ~/rccontrol/enterprise-1/
21 pushd ~/.rccontrol/enterprise-1/
22 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 28 rcextensions are loaded when |RCE| starts. So a restart is required after activation or
@@ -104,7 +104,7 b' Upgrade notes'
104 104 - In this release, we're shipping a new `rcextensions`. The changes made are
105 105 backward incompatible. An update of `rcextensions` is required
106 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 108 Old code should be 100% portable by just copy&paste to the right function.
109 109
110 110 - Mailing: We introduced a new mailing library. The older options should be compatible and
@@ -9,6 +9,7 b' Release Notes'
9 9 .. toctree::
10 10 :maxdepth: 1
11 11
12 release-notes-4.16.0.rst
12 13 release-notes-4.15.2.rst
13 14 release-notes-4.15.1.rst
14 15 release-notes-4.15.0.rst
@@ -516,7 +516,7 b' Example usage:'
516 516 $ ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
517 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 520 # This is using pre-350 virtualenv
521 521 (venv)$ rhodecode-index --instance-name=enterprise-1
522 522
@@ -527,7 +527,7 b' Example usage:'
527 527
528 528 # Create the indexing mapping file
529 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 532 .. _tools-rhodecode-list-instance:
533 533
@@ -52,7 +52,7 b''
52 52 "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js",
53 53 "<%= dirs.js.src %>/plugins/jquery.autocomplete.js",
54 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 56 "<%= dirs.js.src %>/plugins/jquery.timeago.js",
57 57 "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js",
58 58 "<%= dirs.js.src %>/select2/select2.js",
@@ -22,6 +22,7 b''
22 22 "grunt-contrib-watch": "^0.6.1",
23 23 "grunt-webpack": "^3.1.3",
24 24 "jquery": "1.11.3",
25 "mark.js": "8.11.1",
25 26 "jshint": "^2.9.1-rc3",
26 27 "moment": "^2.18.1",
27 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 409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
410 410 };
411 411 };
412 "@webcomponents/shadycss-1.6.0" = {
412 "@webcomponents/shadycss-1.7.1" = {
413 413 name = "_at_webcomponents_slash_shadycss";
414 414 packageName = "@webcomponents/shadycss";
415 version = "1.6.0";
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.6.0.tgz";
418 sha512 = "iURGZZU6BaiRJtGgjMn208QxPkY11QwT/VmuHNa4Yb+kJxU/WODe4C8b0LDOtnk4KJzJg50hCfwvPRAjePEzbA==";
415 version = "1.7.1";
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.7.1.tgz";
418 sha512 = "6SZqLajRPWL0rrKDZOGF8PCBq5B9JqgFmE5rX5psk6i8WrqiMkSCuO8+rnirzViTsU5CqnjQPFC3OvG4YJdMrQ==";
419 419 };
420 420 };
421 421 "@webcomponents/webcomponentsjs-2.2.1" = {
@@ -499,13 +499,13 b' let'
499 499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
500 500 };
501 501 };
502 "ajv-6.6.1" = {
502 "ajv-6.6.2" = {
503 503 name = "ajv";
504 504 packageName = "ajv";
505 version = "6.6.1";
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz";
508 sha512 = "ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==";
505 version = "6.6.2";
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz";
508 sha512 = "FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==";
509 509 };
510 510 };
511 511 "ajv-keywords-3.2.0" = {
@@ -815,15 +815,6 b' let'
815 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 818 "async-2.6.1" = {
828 819 name = "async";
829 820 packageName = "async";
@@ -1445,6 +1436,15 b' let'
1445 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 1448 "binary-extensions-1.12.0" = {
1449 1449 name = "binary-extensions";
1450 1450 packageName = "binary-extensions";
@@ -1679,22 +1679,22 b' let'
1679 1679 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1680 1680 };
1681 1681 };
1682 "caniuse-db-1.0.30000912" = {
1682 "caniuse-db-1.0.30000927" = {
1683 1683 name = "caniuse-db";
1684 1684 packageName = "caniuse-db";
1685 version = "1.0.30000912";
1686 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000912.tgz";
1688 sha512 = "uiepPdHcJ06Na9t15L5l+pp3NWQU4IETbmleghD6tqCqbIYqhHSu7nVfbK2gqPjfy+9jl/wHF1UQlyTszh9tJQ==";
1689 };
1690 };
1691 "caniuse-lite-1.0.30000912" = {
1685 version = "1.0.30000927";
1686 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000927.tgz";
1688 sha512 = "CX/QvLA8oh7kQ9cHCCzFm0UZW4KwSyQSRJ5A1XtH42HaMJQ0yh+9fEVWagMqv9I1vSCtaqA5Mb8k0uKfv7jhDw==";
1689 };
1690 };
1691 "caniuse-lite-1.0.30000927" = {
1692 1692 name = "caniuse-lite";
1693 1693 packageName = "caniuse-lite";
1694 version = "1.0.30000912";
1695 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz";
1697 sha512 = "M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==";
1694 version = "1.0.30000927";
1695 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz";
1697 sha512 = "ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==";
1698 1698 };
1699 1699 };
1700 1700 "caseless-0.12.0" = {
@@ -1733,13 +1733,13 b' let'
1733 1733 sha1 = "a8115c55e4a702fe4d150abd3872822a7e09fc98";
1734 1734 };
1735 1735 };
1736 "chalk-2.4.1" = {
1736 "chalk-2.4.2" = {
1737 1737 name = "chalk";
1738 1738 packageName = "chalk";
1739 version = "2.4.1";
1740 src = fetchurl {
1741 url = "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz";
1742 sha512 = "ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==";
1739 version = "2.4.2";
1740 src = fetchurl {
1741 url = "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz";
1742 sha512 = "Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==";
1743 1743 };
1744 1744 };
1745 1745 "chokidar-2.0.4" = {
@@ -1958,15 +1958,6 b' let'
1958 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 1961 "colors-1.1.2" = {
1971 1962 name = "colors";
1972 1963 packageName = "colors";
@@ -1976,13 +1967,13 b' let'
1976 1967 sha1 = "168a4701756b6a7f51a12ce0c97bfa28c084ed63";
1977 1968 };
1978 1969 };
1979 "colors-1.3.2" = {
1970 "colors-1.3.3" = {
1980 1971 name = "colors";
1981 1972 packageName = "colors";
1982 version = "1.3.2";
1983 src = fetchurl {
1984 url = "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz";
1985 sha512 = "rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==";
1973 version = "1.3.3";
1974 src = fetchurl {
1975 url = "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz";
1976 sha512 = "mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==";
1986 1977 };
1987 1978 };
1988 1979 "combined-stream-1.0.7" = {
@@ -2102,13 +2093,13 b' let'
2102 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 2097 name = "core-js";
2107 2098 packageName = "core-js";
2108 version = "2.5.7";
2109 src = fetchurl {
2110 url = "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz";
2111 sha512 = "RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==";
2099 version = "2.6.1";
2100 src = fetchurl {
2101 url = "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz";
2102 sha512 = "L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==";
2112 2103 };
2113 2104 };
2114 2105 "core-util-is-1.0.2" = {
@@ -2246,15 +2237,6 b' let'
2246 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 2240 "cyclist-0.2.2" = {
2259 2241 name = "cyclist";
2260 2242 packageName = "cyclist";
@@ -2489,13 +2471,13 b' let'
2489 2471 sha1 = "bd28773e2642881aec51544924299c5cd822185b";
2490 2472 };
2491 2473 };
2492 "domelementtype-1.3.0" = {
2474 "domelementtype-1.3.1" = {
2493 2475 name = "domelementtype";
2494 2476 packageName = "domelementtype";
2495 version = "1.3.0";
2496 src = fetchurl {
2497 url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz";
2498 sha1 = "b17aed82e8ab59e52dd9c19b1756e0fc187204c2";
2477 version = "1.3.1";
2478 src = fetchurl {
2479 url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz";
2480 sha512 = "BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==";
2499 2481 };
2500 2482 };
2501 2483 "domhandler-2.1.0" = {
@@ -2552,13 +2534,13 b' let'
2552 2534 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2553 2535 };
2554 2536 };
2555 "electron-to-chromium-1.3.85" = {
2537 "electron-to-chromium-1.3.98" = {
2556 2538 name = "electron-to-chromium";
2557 2539 packageName = "electron-to-chromium";
2558 version = "1.3.85";
2559 src = fetchurl {
2560 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.85.tgz";
2561 sha512 = "kWSDVVF9t3mft2OHVZy4K85X2beP6c6mFm3teFS/mLSDJpQwuFIWHrULCX+w6H1E55ZYmFRlT+ATAFRwhrYzsw==";
2540 version = "1.3.98";
2541 src = fetchurl {
2542 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.98.tgz";
2543 sha512 = "WIZdNuvE3dFr6kkPgv4d/cfswNZD6XbeLBM8baOIQTsnbf4xWrVEaLvp7oNnbnMWWXDqq7Tbv+H5JfciLTJm4Q==";
2562 2544 };
2563 2545 };
2564 2546 "elliptic-6.4.1" = {
@@ -2633,13 +2615,13 b' let'
2633 2615 sha512 = "MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==";
2634 2616 };
2635 2617 };
2636 "es-abstract-1.12.0" = {
2618 "es-abstract-1.13.0" = {
2637 2619 name = "es-abstract";
2638 2620 packageName = "es-abstract";
2639 version = "1.12.0";
2640 src = fetchurl {
2641 url = "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz";
2642 sha512 = "C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==";
2621 version = "1.13.0";
2622 src = fetchurl {
2623 url = "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz";
2624 sha512 = "vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==";
2643 2625 };
2644 2626 };
2645 2627 "es-to-primitive-1.2.0" = {
@@ -2651,15 +2633,6 b' let'
2651 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 2636 "es6-templates-0.2.3" = {
2664 2637 name = "es6-templates";
2665 2638 packageName = "es6-templates";
@@ -2777,13 +2750,13 b' let'
2777 2750 sha512 = "/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==";
2778 2751 };
2779 2752 };
2780 "execa-0.10.0" = {
2753 "execa-1.0.0" = {
2781 2754 name = "execa";
2782 2755 packageName = "execa";
2783 version = "0.10.0";
2784 src = fetchurl {
2785 url = "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz";
2786 sha512 = "7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==";
2756 version = "1.0.0";
2757 src = fetchurl {
2758 url = "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz";
2759 sha512 = "adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==";
2787 2760 };
2788 2761 };
2789 2762 "exit-0.1.2" = {
@@ -2858,15 +2831,6 b' let'
2858 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 2834 "extsprintf-1.3.0" = {
2871 2835 name = "extsprintf";
2872 2836 packageName = "extsprintf";
@@ -2876,15 +2840,6 b' let'
2876 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 2843 "fast-deep-equal-2.0.1" = {
2889 2844 name = "fast-deep-equal";
2890 2845 packageName = "fast-deep-equal";
@@ -2930,15 +2885,6 b' let'
2930 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 2888 "file-sync-cmp-0.1.1" = {
2943 2889 name = "file-sync-cmp";
2944 2890 packageName = "file-sync-cmp";
@@ -3002,22 +2948,22 b' let'
3002 2948 sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc";
3003 2949 };
3004 2950 };
3005 "fined-1.1.0" = {
2951 "fined-1.1.1" = {
3006 2952 name = "fined";
3007 2953 packageName = "fined";
3008 version = "1.1.0";
3009 src = fetchurl {
3010 url = "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz";
3011 sha1 = "b37dc844b76a2f5e7081e884f7c0ae344f153476";
3012 };
3013 };
3014 "flagged-respawn-1.0.0" = {
2954 version = "1.1.1";
2955 src = fetchurl {
2956 url = "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz";
2957 sha512 = "jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==";
2958 };
2959 };
2960 "flagged-respawn-1.0.1" = {
3015 2961 name = "flagged-respawn";
3016 2962 packageName = "flagged-respawn";
3017 version = "1.0.0";
3018 src = fetchurl {
3019 url = "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz";
3020 sha1 = "4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7";
2963 version = "1.0.1";
2964 src = fetchurl {
2965 url = "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz";
2966 sha512 = "lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==";
3021 2967 };
3022 2968 };
3023 2969 "flatten-1.0.2" = {
@@ -3092,15 +3038,6 b' let'
3092 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 3041 "fs-write-stream-atomic-1.0.10" = {
3105 3042 name = "fs-write-stream-atomic";
3106 3043 packageName = "fs-write-stream-atomic";
@@ -3155,13 +3092,13 b' let'
3155 3092 sha512 = "3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==";
3156 3093 };
3157 3094 };
3158 "get-stream-3.0.0" = {
3095 "get-stream-4.1.0" = {
3159 3096 name = "get-stream";
3160 3097 packageName = "get-stream";
3161 version = "3.0.0";
3162 src = fetchurl {
3163 url = "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz";
3164 sha1 = "8e943d1358dc37555054ecbe2edb05aa174ede14";
3098 version = "4.1.0";
3099 src = fetchurl {
3100 url = "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz";
3101 sha512 = "GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==";
3165 3102 };
3166 3103 };
3167 3104 "get-value-2.0.6" = {
@@ -3236,13 +3173,13 b' let'
3236 3173 sha512 = "sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==";
3237 3174 };
3238 3175 };
3239 "global-modules-path-2.3.0" = {
3176 "global-modules-path-2.3.1" = {
3240 3177 name = "global-modules-path";
3241 3178 packageName = "global-modules-path";
3242 version = "2.3.0";
3243 src = fetchurl {
3244 url = "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz";
3245 sha512 = "HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==";
3179 version = "2.3.1";
3180 src = fetchurl {
3181 url = "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz";
3182 sha512 = "y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==";
3246 3183 };
3247 3184 };
3248 3185 "global-prefix-1.0.2" = {
@@ -3533,22 +3470,13 b' let'
3533 3470 sha1 = "5fc8686847ecd73499403319a6b0a3f3f6ae4918";
3534 3471 };
3535 3472 };
3536 "hash.js-1.1.5" = {
3473 "hash.js-1.1.7" = {
3537 3474 name = "hash.js";
3538 3475 packageName = "hash.js";
3539 version = "1.1.5";
3540 src = fetchurl {
3541 url = "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz";
3542 sha512 = "eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==";
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";
3476 version = "1.1.7";
3477 src = fetchurl {
3478 url = "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz";
3479 sha512 = "taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==";
3552 3480 };
3553 3481 };
3554 3482 "hawk-3.1.3" = {
@@ -4217,13 +4145,13 b' let'
4217 4145 sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583";
4218 4146 };
4219 4147 };
4220 "js-base64-2.4.9" = {
4148 "js-base64-2.5.0" = {
4221 4149 name = "js-base64";
4222 4150 packageName = "js-base64";
4223 version = "2.4.9";
4224 src = fetchurl {
4225 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz";
4226 sha512 = "xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==";
4151 version = "2.5.0";
4152 src = fetchurl {
4153 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz";
4154 sha512 = "wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==";
4227 4155 };
4228 4156 };
4229 4157 "js-tokens-3.0.2" = {
@@ -4280,13 +4208,13 b' let'
4280 4208 sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b";
4281 4209 };
4282 4210 };
4283 "jshint-2.9.6" = {
4211 "jshint-2.9.7" = {
4284 4212 name = "jshint";
4285 4213 packageName = "jshint";
4286 version = "2.9.6";
4287 src = fetchurl {
4288 url = "https://registry.npmjs.org/jshint/-/jshint-2.9.6.tgz";
4289 sha512 = "KO9SIAKTlJQOM4lE64GQUtGBRpTOuvbrRrSZw3AhUxMNG266nX9hK2cKA4SBhXOj0irJGyNyGSLT62HGOVDEOA==";
4214 version = "2.9.7";
4215 src = fetchurl {
4216 url = "https://registry.npmjs.org/jshint/-/jshint-2.9.7.tgz";
4217 sha512 = "Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA==";
4290 4218 };
4291 4219 };
4292 4220 "json-parse-better-errors-1.0.2" = {
@@ -4343,13 +4271,13 b' let'
4343 4271 sha1 = "1eade7acc012034ad84e2396767ead9fa5495821";
4344 4272 };
4345 4273 };
4346 "jsonfile-2.4.0" = {
4347 name = "jsonfile";
4348 packageName = "jsonfile";
4349 version = "2.4.0";
4350 src = fetchurl {
4351 url = "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz";
4352 sha1 = "3736a2b428b87bbda0cc83b53fa3d633a35c2ae8";
4274 "json5-1.0.1" = {
4275 name = "json5";
4276 packageName = "json5";
4277 version = "1.0.1";
4278 src = fetchurl {
4279 url = "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz";
4280 sha512 = "aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==";
4353 4281 };
4354 4282 };
4355 4283 "jsonify-0.0.0" = {
@@ -4370,15 +4298,6 b' let'
4370 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 4301 "kind-of-3.2.2" = {
4383 4302 name = "kind-of";
4384 4303 packageName = "kind-of";
@@ -4415,15 +4334,6 b' let'
4415 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 4337 "lazy-cache-1.0.4" = {
4428 4338 name = "lazy-cache";
4429 4339 packageName = "lazy-cache";
@@ -4478,13 +4388,13 b' let'
4478 4388 sha1 = "f86e6374d43205a6e6c60e9196f17c0299bfb348";
4479 4389 };
4480 4390 };
4481 "loader-utils-1.1.0" = {
4391 "loader-utils-1.2.3" = {
4482 4392 name = "loader-utils";
4483 4393 packageName = "loader-utils";
4484 version = "1.1.0";
4485 src = fetchurl {
4486 url = "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz";
4487 sha1 = "c98aef488bcceda2ffb5e2de646d6a754429f5cd";
4394 version = "1.2.3";
4395 src = fetchurl {
4396 url = "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz";
4397 sha512 = "fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==";
4488 4398 };
4489 4399 };
4490 4400 "locate-path-2.0.0" = {
@@ -4676,6 +4586,15 b' let'
4676 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 4598 "math-expression-evaluator-1.2.17" = {
4680 4599 name = "math-expression-evaluator";
4681 4600 packageName = "math-expression-evaluator";
@@ -4820,6 +4739,15 b' let'
4820 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 4751 "mississippi-2.0.0" = {
4824 4752 name = "mississippi";
4825 4753 packageName = "mississippi";
@@ -4847,13 +4775,13 b' let'
4847 4775 sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903";
4848 4776 };
4849 4777 };
4850 "moment-2.22.2" = {
4778 "moment-2.23.0" = {
4851 4779 name = "moment";
4852 4780 packageName = "moment";
4853 version = "2.22.2";
4854 src = fetchurl {
4855 url = "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz";
4856 sha1 = "3c257f9839fc0e93ff53149632239eb90783ff66";
4781 version = "2.23.0";
4782 src = fetchurl {
4783 url = "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz";
4784 sha512 = "3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==";
4857 4785 };
4858 4786 };
4859 4787 "mousetrap-1.6.2" = {
@@ -4883,13 +4811,13 b' let'
4883 4811 sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8";
4884 4812 };
4885 4813 };
4886 "nan-2.11.1" = {
4814 "nan-2.12.1" = {
4887 4815 name = "nan";
4888 4816 packageName = "nan";
4889 version = "2.11.1";
4890 src = fetchurl {
4891 url = "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz";
4892 sha512 = "iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==";
4817 version = "2.12.1";
4818 src = fetchurl {
4819 url = "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz";
4820 sha512 = "JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==";
4893 4821 };
4894 4822 };
4895 4823 "nanomatch-1.2.13" = {
@@ -5144,13 +5072,13 b' let'
5144 5072 sha1 = "ffbc4988336e0e833de0c168c7ef152121aa7fb3";
5145 5073 };
5146 5074 };
5147 "os-locale-3.0.1" = {
5075 "os-locale-3.1.0" = {
5148 5076 name = "os-locale";
5149 5077 packageName = "os-locale";
5150 version = "3.0.1";
5151 src = fetchurl {
5152 url = "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz";
5153 sha512 = "7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==";
5078 version = "3.1.0";
5079 src = fetchurl {
5080 url = "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz";
5081 sha512 = "Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==";
5154 5082 };
5155 5083 };
5156 5084 "os-tmpdir-1.0.2" = {
@@ -5207,13 +5135,13 b' let'
5207 5135 sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==";
5208 5136 };
5209 5137 };
5210 "p-limit-2.0.0" = {
5138 "p-limit-2.1.0" = {
5211 5139 name = "p-limit";
5212 5140 packageName = "p-limit";
5213 version = "2.0.0";
5214 src = fetchurl {
5215 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz";
5216 sha512 = "fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==";
5141 version = "2.1.0";
5142 src = fetchurl {
5143 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz";
5144 sha512 = "NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==";
5217 5145 };
5218 5146 };
5219 5147 "p-locate-2.0.0" = {
@@ -5432,15 +5360,6 b' let'
5432 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 5363 "performance-now-0.2.0" = {
5445 5364 name = "performance-now";
5446 5365 packageName = "performance-now";
@@ -5450,24 +5369,6 b' let'
5450 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 5372 "pify-3.0.0" = {
5472 5373 name = "pify";
5473 5374 packageName = "pify";
@@ -5477,24 +5378,6 b' let'
5477 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 5381 "pkg-dir-2.0.0" = {
5499 5382 name = "pkg-dir";
5500 5383 packageName = "pkg-dir";
@@ -5882,15 +5765,6 b' let'
5882 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 5768 "promise-7.3.1" = {
5895 5769 name = "promise";
5896 5770 packageName = "promise";
@@ -5945,6 +5819,15 b' let'
5945 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 5831 "pumpify-1.5.1" = {
5949 5832 name = "pumpify";
5950 5833 packageName = "pumpify";
@@ -6278,15 +6161,6 b' let'
6278 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 6164 "require-directory-2.1.1" = {
6291 6165 name = "require-directory";
6292 6166 packageName = "require-directory";
@@ -6305,13 +6179,13 b' let'
6305 6179 sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1";
6306 6180 };
6307 6181 };
6308 "resolve-1.8.1" = {
6182 "resolve-1.9.0" = {
6309 6183 name = "resolve";
6310 6184 packageName = "resolve";
6311 version = "1.8.1";
6312 src = fetchurl {
6313 url = "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz";
6314 sha512 = "AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==";
6185 version = "1.9.0";
6186 src = fetchurl {
6187 url = "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz";
6188 sha512 = "TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==";
6315 6189 };
6316 6190 };
6317 6191 "resolve-cwd-2.0.0" = {
@@ -6377,13 +6251,13 b' let'
6377 6251 sha1 = "e439be2aaee327321952730f99a8929e4fc50582";
6378 6252 };
6379 6253 };
6380 "rimraf-2.6.2" = {
6254 "rimraf-2.6.3" = {
6381 6255 name = "rimraf";
6382 6256 packageName = "rimraf";
6383 version = "2.6.2";
6384 src = fetchurl {
6385 url = "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz";
6386 sha512 = "lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==";
6257 version = "2.6.3";
6258 src = fetchurl {
6259 url = "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz";
6260 sha512 = "mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==";
6387 6261 };
6388 6262 };
6389 6263 "ripemd160-2.0.2" = {
@@ -6467,13 +6341,13 b' let'
6467 6341 sha512 = "RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==";
6468 6342 };
6469 6343 };
6470 "serialize-javascript-1.5.0" = {
6344 "serialize-javascript-1.6.1" = {
6471 6345 name = "serialize-javascript";
6472 6346 packageName = "serialize-javascript";
6473 version = "1.5.0";
6474 src = fetchurl {
6475 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz";
6476 sha512 = "Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==";
6347 version = "1.6.1";
6348 src = fetchurl {
6349 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz";
6350 sha512 = "A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==";
6477 6351 };
6478 6352 };
6479 6353 "set-blocking-2.0.0" = {
@@ -6701,15 +6575,6 b' let'
6701 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 6578 "split-string-3.1.0" = {
6714 6579 name = "split-string";
6715 6580 packageName = "split-string";
@@ -6728,13 +6593,13 b' let'
6728 6593 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6729 6594 };
6730 6595 };
6731 "sshpk-1.15.2" = {
6596 "sshpk-1.16.0" = {
6732 6597 name = "sshpk";
6733 6598 packageName = "sshpk";
6734 version = "1.15.2";
6735 src = fetchurl {
6736 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz";
6737 sha512 = "Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==";
6599 version = "1.16.0";
6600 src = fetchurl {
6601 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz";
6602 sha512 = "Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==";
6738 6603 };
6739 6604 };
6740 6605 "ssri-5.3.0" = {
@@ -6746,15 +6611,6 b' let'
6746 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 6614 "static-extend-0.1.2" = {
6759 6615 name = "static-extend";
6760 6616 packageName = "static-extend";
@@ -6989,15 +6845,6 b' let'
6989 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 6848 "through-2.3.8" = {
7002 6849 name = "through";
7003 6850 packageName = "through";
@@ -7259,15 +7106,6 b' let'
7259 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 7109 "union-value-1.0.0" = {
7272 7110 name = "union-value";
7273 7111 packageName = "union-value";
@@ -7439,13 +7277,13 b' let'
7439 7277 sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==";
7440 7278 };
7441 7279 };
7442 "v8flags-3.1.1" = {
7280 "v8flags-3.1.2" = {
7443 7281 name = "v8flags";
7444 7282 packageName = "v8flags";
7445 version = "3.1.1";
7446 src = fetchurl {
7447 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz";
7448 sha512 = "iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==";
7283 version = "3.1.2";
7284 src = fetchurl {
7285 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz";
7286 sha512 = "MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==";
7449 7287 };
7450 7288 };
7451 7289 "vendors-1.0.2" = {
@@ -7583,15 +7421,6 b' let'
7583 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 7424 "wordwrap-0.0.2" = {
7596 7425 name = "wordwrap";
7597 7426 packageName = "wordwrap";
@@ -7682,15 +7511,6 b' let'
7682 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 7515 args = {
7696 7516 name = "rhodecode-enterprise";
@@ -7743,7 +7563,7 b' let'
7743 7563 sources."@webassemblyjs/wasm-parser-1.7.10"
7744 7564 sources."@webassemblyjs/wast-parser-1.7.10"
7745 7565 sources."@webassemblyjs/wast-printer-1.7.10"
7746 sources."@webcomponents/shadycss-1.6.0"
7566 sources."@webcomponents/shadycss-1.7.1"
7747 7567 sources."@webcomponents/webcomponentsjs-2.2.1"
7748 7568 sources."@xtuc/ieee754-1.2.0"
7749 7569 sources."@xtuc/long-4.2.1"
@@ -7818,6 +7638,7 b' let'
7818 7638 })
7819 7639 (sources."babel-core-6.26.3" // {
7820 7640 dependencies = [
7641 sources."json5-0.5.1"
7821 7642 sources."lodash-4.17.11"
7822 7643 sources."minimatch-3.0.4"
7823 7644 ];
@@ -7916,7 +7737,7 b' let'
7916 7737 })
7917 7738 sources."base64-js-1.3.0"
7918 7739 sources."bcrypt-pbkdf-1.0.2"
7919 sources."big.js-3.2.0"
7740 sources."big.js-5.2.2"
7920 7741 sources."binary-extensions-1.12.0"
7921 7742 sources."bluebird-3.5.3"
7922 7743 sources."bn.js-4.11.8"
@@ -7946,7 +7767,7 b' let'
7946 7767 sources."graceful-fs-4.1.15"
7947 7768 sources."lru-cache-4.1.5"
7948 7769 sources."minimatch-3.0.4"
7949 sources."rimraf-2.6.2"
7770 sources."rimraf-2.6.3"
7950 7771 ];
7951 7772 })
7952 7773 sources."cache-base-1.0.1"
@@ -7957,8 +7778,8 b' let'
7957 7778 sources."browserslist-1.7.7"
7958 7779 ];
7959 7780 })
7960 sources."caniuse-db-1.0.30000912"
7961 sources."caniuse-lite-1.0.30000912"
7781 sources."caniuse-db-1.0.30000927"
7782 sources."caniuse-lite-1.0.30000927"
7962 7783 sources."caseless-0.12.0"
7963 7784 sources."center-align-0.1.3"
7964 7785 sources."chalk-0.5.1"
@@ -8045,7 +7866,7 b' let'
8045 7866 dependencies = [
8046 7867 sources."glob-7.1.3"
8047 7868 sources."minimatch-3.0.4"
8048 sources."rimraf-2.6.2"
7869 sources."rimraf-2.6.3"
8049 7870 ];
8050 7871 })
8051 7872 sources."copy-descriptor-0.1.1"
@@ -8055,7 +7876,7 b' let'
8055 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 7880 sources."core-util-is-1.0.2"
8060 7881 sources."create-ecdh-4.0.3"
8061 7882 sources."create-hash-1.2.0"
@@ -8079,7 +7900,6 b' let'
8079 7900 sources."cssesc-0.1.0"
8080 7901 sources."cssnano-3.10.0"
8081 7902 sources."csso-2.3.2"
8082 sources."cycle-1.0.3"
8083 7903 sources."cyclist-0.2.2"
8084 7904 (sources."dashdash-1.14.1" // {
8085 7905 dependencies = [
@@ -8116,7 +7936,7 b' let'
8116 7936 ];
8117 7937 })
8118 7938 sources."domain-browser-1.2.0"
8119 sources."domelementtype-1.3.0"
7939 sources."domelementtype-1.3.1"
8120 7940 sources."domhandler-2.3.0"
8121 7941 sources."domutils-1.5.1"
8122 7942 (sources."duplexify-3.6.1" // {
@@ -8126,7 +7946,7 b' let'
8126 7946 ];
8127 7947 })
8128 7948 sources."ecc-jsbn-0.1.2"
8129 sources."electron-to-chromium-1.3.85"
7949 sources."electron-to-chromium-1.3.98"
8130 7950 sources."elliptic-6.4.1"
8131 7951 sources."emojis-list-2.1.0"
8132 7952 sources."end-of-stream-1.4.1"
@@ -8137,9 +7957,8 b' let'
8137 7957 })
8138 7958 sources."entities-1.0.0"
8139 7959 sources."errno-0.1.7"
8140 sources."es-abstract-1.12.0"
7960 sources."es-abstract-1.13.0"
8141 7961 sources."es-to-primitive-1.2.0"
8142 sources."es6-promise-4.2.5"
8143 7962 sources."es6-templates-0.2.3"
8144 7963 sources."escape-string-regexp-1.0.5"
8145 7964 sources."eslint-scope-4.0.0"
@@ -8151,7 +7970,7 b' let'
8151 7970 sources."eventemitter2-0.4.14"
8152 7971 sources."events-1.1.1"
8153 7972 sources."evp_bytestokey-1.0.3"
8154 sources."execa-0.10.0"
7973 sources."execa-1.0.0"
8155 7974 sources."exit-0.1.2"
8156 7975 (sources."expand-brackets-2.1.4" // {
8157 7976 dependencies = [
@@ -8185,15 +8004,12 b' let'
8185 8004 sources."extend-shallow-2.0.1"
8186 8005 ];
8187 8006 })
8188 sources."extract-zip-1.6.7"
8189 8007 sources."extsprintf-1.3.0"
8190 sources."eyes-0.1.8"
8191 8008 sources."fast-deep-equal-2.0.1"
8192 8009 sources."fast-json-stable-stringify-2.0.0"
8193 8010 sources."fastparse-1.1.2"
8194 8011 sources."favico.js-0.3.10"
8195 8012 sources."faye-websocket-0.4.4"
8196 sources."fd-slicer-1.0.1"
8197 8013 sources."file-sync-cmp-0.1.1"
8198 8014 (sources."fill-range-4.0.0" // {
8199 8015 dependencies = [
@@ -8209,8 +8025,8 b' let'
8209 8025 sources."minimatch-0.3.0"
8210 8026 ];
8211 8027 })
8212 sources."fined-1.1.0"
8213 sources."flagged-respawn-1.0.0"
8028 sources."fined-1.1.1"
8029 sources."flagged-respawn-1.0.1"
8214 8030 sources."flatten-1.0.2"
8215 8031 (sources."flush-write-stream-1.0.3" // {
8216 8032 dependencies = [
@@ -8229,11 +8045,6 b' let'
8229 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 8048 (sources."fs-write-stream-atomic-1.0.10" // {
8238 8049 dependencies = [
8239 8050 sources."graceful-fs-4.1.15"
@@ -8244,7 +8055,11 b' let'
8244 8055 sources."function-bind-1.1.1"
8245 8056 sources."gaze-0.5.2"
8246 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 8063 sources."get-value-2.0.6"
8249 8064 sources."getobject-0.1.0"
8250 8065 (sources."getpass-0.1.7" // {
@@ -8259,7 +8074,7 b' let'
8259 8074 })
8260 8075 sources."glob-parent-3.1.0"
8261 8076 sources."global-modules-1.0.0"
8262 sources."global-modules-path-2.3.0"
8077 sources."global-modules-path-2.3.1"
8263 8078 (sources."global-prefix-1.0.2" // {
8264 8079 dependencies = [
8265 8080 sources."which-1.3.1"
@@ -8351,8 +8166,7 b' let'
8351 8166 ];
8352 8167 })
8353 8168 sources."hash-base-3.0.4"
8354 sources."hash.js-1.1.5"
8355 sources."hasha-2.2.0"
8169 sources."hash.js-1.1.7"
8356 8170 sources."hawk-3.1.3"
8357 8171 sources."he-1.2.0"
8358 8172 sources."hmac-drbg-1.0.1"
@@ -8369,6 +8183,8 b' let'
8369 8183 })
8370 8184 (sources."html-webpack-plugin-3.2.0" // {
8371 8185 dependencies = [
8186 sources."big.js-3.2.0"
8187 sources."json5-0.5.1"
8372 8188 sources."loader-utils-0.2.17"
8373 8189 sources."lodash-4.17.11"
8374 8190 ];
@@ -8381,7 +8197,7 b' let'
8381 8197 (sources."icss-utils-2.1.0" // {
8382 8198 dependencies = [
8383 8199 sources."ansi-styles-3.2.1"
8384 sources."chalk-2.4.1"
8200 sources."chalk-2.4.2"
8385 8201 sources."postcss-6.0.23"
8386 8202 sources."source-map-0.6.1"
8387 8203 sources."supports-color-5.5.0"
@@ -8395,7 +8211,7 b' let'
8395 8211 dependencies = [
8396 8212 sources."find-up-3.0.0"
8397 8213 sources."locate-path-3.0.0"
8398 sources."p-limit-2.0.0"
8214 sources."p-limit-2.1.0"
8399 8215 sources."p-locate-3.0.0"
8400 8216 sources."p-try-2.0.0"
8401 8217 sources."pkg-dir-3.0.0"
@@ -8445,12 +8261,12 b' let'
8445 8261 sources."isobject-3.0.1"
8446 8262 sources."isstream-0.1.2"
8447 8263 sources."jquery-1.11.3"
8448 sources."js-base64-2.4.9"
8264 sources."js-base64-2.5.0"
8449 8265 sources."js-tokens-3.0.2"
8450 8266 sources."js-yaml-2.0.5"
8451 8267 sources."jsbn-0.1.1"
8452 8268 sources."jsesc-1.3.0"
8453 (sources."jshint-2.9.6" // {
8269 (sources."jshint-2.9.7" // {
8454 8270 dependencies = [
8455 8271 sources."lodash-4.17.11"
8456 8272 sources."minimatch-3.0.4"
@@ -8461,25 +8277,14 b' let'
8461 8277 sources."json-schema-traverse-0.4.1"
8462 8278 sources."json-stable-stringify-1.0.1"
8463 8279 sources."json-stringify-safe-5.0.1"
8464 sources."json5-0.5.1"
8465 (sources."jsonfile-2.4.0" // {
8466 dependencies = [
8467 sources."graceful-fs-4.1.15"
8468 ];
8469 })
8280 sources."json5-1.0.1"
8470 8281 sources."jsonify-0.0.0"
8471 8282 (sources."jsprim-1.4.1" // {
8472 8283 dependencies = [
8473 8284 sources."assert-plus-1.0.0"
8474 8285 ];
8475 8286 })
8476 sources."kew-0.7.0"
8477 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 8288 sources."lazy-cache-1.0.4"
8484 8289 sources."lcid-2.0.0"
8485 8290 (sources."less-2.7.3" // {
@@ -8493,7 +8298,7 b' let'
8493 8298 ];
8494 8299 })
8495 8300 sources."loader-runner-2.3.1"
8496 sources."loader-utils-1.1.0"
8301 sources."loader-utils-1.2.3"
8497 8302 sources."locate-path-2.0.0"
8498 8303 sources."lodash-0.9.2"
8499 8304 sources."lodash.camelcase-4.3.0"
@@ -8510,6 +8315,7 b' let'
8510 8315 sources."map-age-cleaner-0.1.3"
8511 8316 sources."map-cache-0.2.2"
8512 8317 sources."map-visit-1.0.0"
8318 sources."mark.js-8.11.1"
8513 8319 sources."math-expression-evaluator-1.2.17"
8514 8320 sources."md5.js-1.3.5"
8515 8321 sources."mem-4.0.0"
@@ -8528,25 +8334,29 b' let'
8528 8334 sources."minimalistic-assert-1.0.1"
8529 8335 sources."minimalistic-crypto-utils-1.0.1"
8530 8336 sources."minimatch-0.2.14"
8531 sources."minimist-0.0.8"
8337 sources."minimist-1.2.0"
8532 8338 sources."mississippi-2.0.0"
8533 8339 (sources."mixin-deep-1.3.1" // {
8534 8340 dependencies = [
8535 8341 sources."is-extendable-1.0.1"
8536 8342 ];
8537 8343 })
8538 sources."mkdirp-0.5.1"
8539 sources."moment-2.22.2"
8344 (sources."mkdirp-0.5.1" // {
8345 dependencies = [
8346 sources."minimist-0.0.8"
8347 ];
8348 })
8349 sources."moment-2.23.0"
8540 8350 sources."mousetrap-1.6.2"
8541 8351 (sources."move-concurrently-1.0.1" // {
8542 8352 dependencies = [
8543 8353 sources."glob-7.1.3"
8544 8354 sources."minimatch-3.0.4"
8545 sources."rimraf-2.6.2"
8355 sources."rimraf-2.6.3"
8546 8356 ];
8547 8357 })
8548 8358 sources."ms-2.0.0"
8549 sources."nan-2.11.1"
8359 sources."nan-2.12.1"
8550 8360 sources."nanomatch-1.2.13"
8551 8361 sources."neo-async-2.6.0"
8552 8362 sources."nice-try-1.0.5"
@@ -8598,7 +8408,7 b' let'
8598 8408 sources."once-1.4.0"
8599 8409 sources."os-browserify-0.3.0"
8600 8410 sources."os-homedir-1.0.2"
8601 sources."os-locale-3.0.1"
8411 sources."os-locale-3.1.0"
8602 8412 sources."os-tmpdir-1.0.2"
8603 8413 sources."osenv-0.1.5"
8604 8414 sources."p-defer-1.0.0"
@@ -8635,22 +8445,13 b' let'
8635 8445 sources."path-root-regex-0.1.2"
8636 8446 sources."path-type-3.0.0"
8637 8447 sources."pbkdf2-3.0.17"
8638 sources."pend-1.2.0"
8639 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 8449 sources."pify-3.0.0"
8647 sources."pinkie-2.0.4"
8648 sources."pinkie-promise-2.0.1"
8649 8450 sources."pkg-dir-2.0.0"
8650 8451 (sources."polymer-webpack-loader-2.0.3" // {
8651 8452 dependencies = [
8652 8453 sources."ansi-styles-3.2.1"
8653 sources."chalk-2.4.1"
8454 sources."chalk-2.4.2"
8654 8455 sources."html-loader-0.5.5"
8655 8456 (sources."postcss-6.0.23" // {
8656 8457 dependencies = [
@@ -8700,7 +8501,7 b' let'
8700 8501 (sources."postcss-modules-extract-imports-1.2.1" // {
8701 8502 dependencies = [
8702 8503 sources."ansi-styles-3.2.1"
8703 sources."chalk-2.4.1"
8504 sources."chalk-2.4.2"
8704 8505 sources."postcss-6.0.23"
8705 8506 sources."source-map-0.6.1"
8706 8507 sources."supports-color-5.5.0"
@@ -8709,7 +8510,7 b' let'
8709 8510 (sources."postcss-modules-local-by-default-1.2.0" // {
8710 8511 dependencies = [
8711 8512 sources."ansi-styles-3.2.1"
8712 sources."chalk-2.4.1"
8513 sources."chalk-2.4.2"
8713 8514 sources."postcss-6.0.23"
8714 8515 sources."source-map-0.6.1"
8715 8516 sources."supports-color-5.5.0"
@@ -8718,7 +8519,7 b' let'
8718 8519 (sources."postcss-modules-scope-1.1.0" // {
8719 8520 dependencies = [
8720 8521 sources."ansi-styles-3.2.1"
8721 sources."chalk-2.4.1"
8522 sources."chalk-2.4.2"
8722 8523 sources."postcss-6.0.23"
8723 8524 sources."source-map-0.6.1"
8724 8525 sources."supports-color-5.5.0"
@@ -8727,7 +8528,7 b' let'
8727 8528 (sources."postcss-modules-values-1.3.0" // {
8728 8529 dependencies = [
8729 8530 sources."ansi-styles-3.2.1"
8730 sources."chalk-2.4.1"
8531 sources."chalk-2.4.2"
8731 8532 sources."postcss-6.0.23"
8732 8533 sources."source-map-0.6.1"
8733 8534 sources."supports-color-5.5.0"
@@ -8749,7 +8550,6 b' let'
8749 8550 sources."private-0.1.8"
8750 8551 sources."process-0.11.10"
8751 8552 sources."process-nextick-args-2.0.0"
8752 sources."progress-1.1.8"
8753 8553 sources."promise-7.3.1"
8754 8554 sources."promise-inflight-1.0.1"
8755 8555 sources."prr-1.0.1"
@@ -8823,10 +8623,9 b' let'
8823 8623 sources."repeat-string-1.6.1"
8824 8624 sources."repeating-2.0.1"
8825 8625 sources."request-2.81.0"
8826 sources."request-progress-2.0.1"
8827 8626 sources."require-directory-2.1.1"
8828 8627 sources."require-main-filename-1.0.1"
8829 sources."resolve-1.8.1"
8628 sources."resolve-1.9.0"
8830 8629 sources."resolve-cwd-2.0.0"
8831 8630 sources."resolve-dir-1.0.1"
8832 8631 sources."resolve-from-3.0.0"
@@ -8842,12 +8641,12 b' let'
8842 8641 sources."sax-1.2.4"
8843 8642 (sources."schema-utils-0.4.7" // {
8844 8643 dependencies = [
8845 sources."ajv-6.6.1"
8644 sources."ajv-6.6.2"
8846 8645 ];
8847 8646 })
8848 8647 sources."select-1.1.2"
8849 8648 sources."semver-5.6.0"
8850 sources."serialize-javascript-1.5.0"
8649 sources."serialize-javascript-1.6.1"
8851 8650 sources."set-blocking-2.0.0"
8852 8651 (sources."set-value-2.0.0" // {
8853 8652 dependencies = [
@@ -8897,16 +8696,14 b' let'
8897 8696 sources."source-map-resolve-0.5.2"
8898 8697 sources."source-map-support-0.4.18"
8899 8698 sources."source-map-url-0.4.0"
8900 sources."split-1.0.1"
8901 8699 sources."split-string-3.1.0"
8902 8700 sources."sprintf-js-1.0.3"
8903 (sources."sshpk-1.15.2" // {
8701 (sources."sshpk-1.16.0" // {
8904 8702 dependencies = [
8905 8703 sources."assert-plus-1.0.0"
8906 8704 ];
8907 8705 })
8908 8706 sources."ssri-5.3.0"
8909 sources."stack-trace-0.0.10"
8910 8707 (sources."static-extend-0.1.2" // {
8911 8708 dependencies = [
8912 8709 sources."define-property-0.2.5"
@@ -8963,7 +8760,6 b' let'
8963 8760 ];
8964 8761 })
8965 8762 sources."tapable-1.1.1"
8966 sources."throttleit-1.0.0"
8967 8763 sources."through-2.3.8"
8968 8764 (sources."through2-2.0.5" // {
8969 8765 dependencies = [
@@ -8993,9 +8789,11 b' let'
8993 8789 sources."trim-right-1.0.1"
8994 8790 (sources."ts-loader-1.3.3" // {
8995 8791 dependencies = [
8996 sources."colors-1.3.2"
8792 sources."big.js-3.2.0"
8793 sources."colors-1.3.3"
8997 8794 sources."enhanced-resolve-3.4.1"
8998 8795 sources."graceful-fs-4.1.15"
8796 sources."json5-0.5.1"
8999 8797 sources."loader-utils-0.2.17"
9000 8798 sources."tapable-0.2.9"
9001 8799 ];
@@ -9025,7 +8823,6 b' let'
9025 8823 sources."unc-path-regex-0.1.2"
9026 8824 sources."underscore-1.7.0"
9027 8825 sources."underscore.string-2.2.1"
9028 sources."unicode-5.2.0-0.7.5"
9029 8826 (sources."union-value-1.0.0" // {
9030 8827 dependencies = [
9031 8828 sources."extend-shallow-2.0.1"
@@ -9066,7 +8863,7 b' let'
9066 8863 sources."utila-0.4.0"
9067 8864 sources."uuid-3.3.2"
9068 8865 sources."v8-compile-cache-2.0.2"
9069 sources."v8flags-3.1.1"
8866 sources."v8flags-3.1.2"
9070 8867 sources."vendors-1.0.2"
9071 8868 (sources."verror-1.10.0" // {
9072 8869 dependencies = [
@@ -9082,13 +8879,13 b' let'
9082 8879 sources."waypoints-4.0.1"
9083 8880 (sources."webpack-4.23.1" // {
9084 8881 dependencies = [
9085 sources."ajv-6.6.1"
8882 sources."ajv-6.6.2"
9086 8883 ];
9087 8884 })
9088 8885 (sources."webpack-cli-3.1.2" // {
9089 8886 dependencies = [
9090 8887 sources."ansi-styles-3.2.1"
9091 sources."chalk-2.4.1"
8888 sources."chalk-2.4.2"
9092 8889 sources."supports-color-5.5.0"
9093 8890 ];
9094 8891 })
@@ -9121,12 +8918,6 b' let'
9121 8918 sources."which-1.0.9"
9122 8919 sources."which-module-2.0.0"
9123 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 8921 sources."wordwrap-0.0.2"
9131 8922 sources."worker-farm-1.6.0"
9132 8923 (sources."wrap-ansi-2.1.0" // {
@@ -9144,13 +8935,12 b' let'
9144 8935 dependencies = [
9145 8936 sources."find-up-3.0.0"
9146 8937 sources."locate-path-3.0.0"
9147 sources."p-limit-2.0.0"
8938 sources."p-limit-2.1.0"
9148 8939 sources."p-locate-3.0.0"
9149 8940 sources."p-try-2.0.0"
9150 8941 ];
9151 8942 })
9152 8943 sources."yargs-parser-11.1.1"
9153 sources."yauzl-2.4.1"
9154 8944 ];
9155 8945 buildInputs = globalBuildInputs;
9156 8946 meta = {
@@ -219,11 +219,11 b' self: super: {'
219 219 };
220 220 };
221 221 "click" = super.buildPythonPackage {
222 name = "click-6.6";
222 name = "click-7.0";
223 223 doCheck = false;
224 224 src = fetchurl {
225 url = "https://files.pythonhosted.org/packages/7a/00/c14926d8232b36b08218067bcd5853caefb4737cda3f0a47437151344792/click-6.6.tar.gz";
226 sha256 = "1sggipyz52crrybwbr9xvwxd4aqigvplf53k9w3ygxmzivd1jsnc";
225 url = "https://files.pythonhosted.org/packages/f8/5c/f60e9d8a1e77005f664b76ff8aeaee5bc05d0a91798afd7f53fc998dbc47/Click-7.0.tar.gz";
226 sha256 = "1mzjixd4vjbjvzb6vylki9w1556a9qmdh35kzmq6cign46av952v";
227 227 };
228 228 meta = {
229 229 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -260,11 +260,11 b' self: super: {'
260 260 };
261 261 };
262 262 "configparser" = super.buildPythonPackage {
263 name = "configparser-3.5.0";
263 name = "configparser-3.7.1";
264 264 doCheck = false;
265 265 src = fetchurl {
266 url = "https://files.pythonhosted.org/packages/7c/69/c2ce7e91c89dc073eb1aa74c0621c3eefbffe8216b3f9af9d3885265c01c/configparser-3.5.0.tar.gz";
267 sha256 = "0fi7vf09vi1588jd8f16a021m5y6ih2hy7rpbjb408xw45qb822k";
266 url = "https://files.pythonhosted.org/packages/b6/a6/eceea7c5a5dbcf56815bed411c38cabd8a879386be10717b160e7362b5a2/configparser-3.7.1.tar.gz";
267 sha256 = "0cnz213il9lhgda6x70fw7mfqr8da43s3wm343lwzhqx94mgmmav";
268 268 };
269 269 meta = {
270 270 license = [ pkgs.lib.licenses.mit ];
@@ -374,11 +374,14 b' self: super: {'
374 374 };
375 375 };
376 376 "dogpile.cache" = super.buildPythonPackage {
377 name = "dogpile.cache-0.6.7";
377 name = "dogpile.cache-0.7.1";
378 378 doCheck = false;
379 propagatedBuildInputs = [
380 self."decorator"
381 ];
379 382 src = fetchurl {
380 url = "https://files.pythonhosted.org/packages/ee/bd/440da735a11c6087eed7cc8747fc4b995cbac2464168682f8ee1c8e43844/dogpile.cache-0.6.7.tar.gz";
381 sha256 = "1aw8rx8vhb75y7zc6gi67g21sw057jdx7i8m3jq7kf3nqavxx9zw";
383 url = "https://files.pythonhosted.org/packages/84/3e/dbf1cfc5228f1d3dca80ef714db2c5aaec5cd9efaf54d7e3daef6bc48b19/dogpile.cache-0.7.1.tar.gz";
384 sha256 = "0caazmrzhnfqb5yrp8myhw61ny637jj69wcngrpbvi31jlcpy6v9";
382 385 };
383 386 meta = {
384 387 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -407,30 +410,75 b' self: super: {'
407 410 };
408 411 };
409 412 "elasticsearch" = super.buildPythonPackage {
410 name = "elasticsearch-2.3.0";
413 name = "elasticsearch-6.3.1";
411 414 doCheck = false;
412 415 propagatedBuildInputs = [
413 416 self."urllib3"
414 417 ];
415 418 src = fetchurl {
416 url = "https://files.pythonhosted.org/packages/10/35/5fd52c5f0b0ee405ed4b5195e8bce44c5e041787680dc7b94b8071cac600/elasticsearch-2.3.0.tar.gz";
417 sha256 = "10ad2dk73xsys9vajwsncibs69asa63w1hgwz6lz1prjpyi80c5y";
419 url = "https://files.pythonhosted.org/packages/9d/ce/c4664e8380e379a9402ecfbaf158e56396da90d520daba21cfa840e0eb71/elasticsearch-6.3.1.tar.gz";
420 sha256 = "12y93v0yn7a4xmf969239g8gb3l4cdkclfpbk1qc8hx5qkymrnma";
418 421 };
419 422 meta = {
420 423 license = [ pkgs.lib.licenses.asl20 ];
421 424 };
422 425 };
423 426 "elasticsearch-dsl" = super.buildPythonPackage {
424 name = "elasticsearch-dsl-2.2.0";
427 name = "elasticsearch-dsl-6.3.1";
425 428 doCheck = false;
426 429 propagatedBuildInputs = [
427 430 self."six"
428 431 self."python-dateutil"
429 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 449 src = fetchurl {
432 url = "https://files.pythonhosted.org/packages/66/2f/52a086968788e58461641570f45c3207a52d46ebbe9b77dc22b6a8ffda66/elasticsearch-dsl-2.2.0.tar.gz";
433 sha256 = "1g4kxzxsdwlsl2a9kscmx11pafgimhj7y8wrfksv8pgvpkfb9fwr";
450 url = "https://files.pythonhosted.org/packages/a6/eb/73e75f9681fa71e3157b8ee878534235d57f24ee64f0e77f8d995fb57076/elasticsearch1-1.10.0.tar.gz";
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 483 meta = {
436 484 license = [ pkgs.lib.licenses.asl20 ];
@@ -517,14 +565,14 b' self: super: {'
517 565 };
518 566 };
519 567 "gevent" = super.buildPythonPackage {
520 name = "gevent-1.3.7";
568 name = "gevent-1.4.0";
521 569 doCheck = false;
522 570 propagatedBuildInputs = [
523 571 self."greenlet"
524 572 ];
525 573 src = fetchurl {
526 url = "https://files.pythonhosted.org/packages/10/c1/9499b146bfa43aa4f1e0ed1bab1bd3209a4861d25650c11725036c731cf5/gevent-1.3.7.tar.gz";
527 sha256 = "0b0fr04qdk1p4sniv87fh8z5psac60x01pv054kpgi94520g81iz";
574 url = "https://files.pythonhosted.org/packages/ed/27/6c49b70808f569b66ec7fac2e78f076e9b204db9cf5768740cff3d5a07ae/gevent-1.4.0.tar.gz";
575 sha256 = "1lchr4akw2jkm5v4kz7bdm4wv3knkfhbfn9vkkz4s5yrkcxzmdqy";
528 576 };
529 577 meta = {
530 578 license = [ pkgs.lib.licenses.mit ];
@@ -673,11 +721,11 b' self: super: {'
673 721 };
674 722 };
675 723 "iso8601" = super.buildPythonPackage {
676 name = "iso8601-0.1.11";
724 name = "iso8601-0.1.12";
677 725 doCheck = false;
678 726 src = fetchurl {
679 url = "https://files.pythonhosted.org/packages/c0/75/c9209ee4d1b5975eb8c2cba4428bde6b61bd55664a98290dd015cdb18e98/iso8601-0.1.11.tar.gz";
680 sha256 = "0c7gh3lsdjds262h0v1sqc66l7hqgfwbakn96qrhdbl0i3vm5yz8";
727 url = "https://files.pythonhosted.org/packages/45/13/3db24895497345fb44c4248c08b16da34a9eb02643cea2754b21b5ed08b0/iso8601-0.1.12.tar.gz";
728 sha256 = "10nyvvnrhw2w3p09v1ica4lgj6f4g9j3kkfx17qmraiq3w7b5i29";
681 729 };
682 730 meta = {
683 731 license = [ pkgs.lib.licenses.mit ];
@@ -768,14 +816,14 b' self: super: {'
768 816 };
769 817 };
770 818 "kombu" = super.buildPythonPackage {
771 name = "kombu-4.2.0";
819 name = "kombu-4.2.1";
772 820 doCheck = false;
773 821 propagatedBuildInputs = [
774 822 self."amqp"
775 823 ];
776 824 src = fetchurl {
777 url = "https://files.pythonhosted.org/packages/ab/b1/46a7a8babf5e60f3b2ca081a100af8edfcf132078a726375f52a054e70cf/kombu-4.2.0.tar.gz";
778 sha256 = "1yz19qlqf0inl1mnwlpq9j6kj9r67clpy0xg99phyg4329rw80fn";
825 url = "https://files.pythonhosted.org/packages/39/9f/556b988833abede4a80dbd18b2bdf4e8ff4486dd482ed45da961347e8ed2/kombu-4.2.1.tar.gz";
826 sha256 = "10lh3hncvw67fz0k5vgbx3yh9gjfpqdlia1f13i28cgnc1nfrbc6";
779 827 };
780 828 meta = {
781 829 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -818,11 +866,11 b' self: super: {'
818 866 };
819 867 };
820 868 "markupsafe" = super.buildPythonPackage {
821 name = "markupsafe-1.0";
869 name = "markupsafe-1.1.0";
822 870 doCheck = false;
823 871 src = fetchurl {
824 url = "https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz";
825 sha256 = "0rdn1s8x9ni7ss8rfiacj7x1085lx8mh2zdwqslnw8xc3l4nkgm6";
872 url = "https://files.pythonhosted.org/packages/ac/7e/1b4c2e05809a4414ebce0892fe1e32c14ace86ca7d50c70f00979ca9b3a3/MarkupSafe-1.1.0.tar.gz";
873 sha256 = "1lxirjypbdd3l9jl4vliilhfnhy7c7f2vlldqg1b0i74khn375sf";
826 874 };
827 875 meta = {
828 876 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -862,14 +910,14 b' self: super: {'
862 910 };
863 911 };
864 912 "more-itertools" = super.buildPythonPackage {
865 name = "more-itertools-4.3.0";
913 name = "more-itertools-5.0.0";
866 914 doCheck = false;
867 915 propagatedBuildInputs = [
868 916 self."six"
869 917 ];
870 918 src = fetchurl {
871 url = "https://files.pythonhosted.org/packages/88/ff/6d485d7362f39880810278bdc906c13300db05485d9c65971dec1142da6a/more-itertools-4.3.0.tar.gz";
872 sha256 = "17h3na0rdh8xq30w4b9pizgkdxmm51896bxw600x84jflg9vaxn4";
919 url = "https://files.pythonhosted.org/packages/dd/26/30fc0d541d9fdf55faf5ba4b0fd68f81d5bd2447579224820ad525934178/more-itertools-5.0.0.tar.gz";
920 sha256 = "1r12cm6mcdwdzz7d47a6g4l437xsvapdlgyhqay3i2nrlv03da9q";
873 921 };
874 922 meta = {
875 923 license = [ pkgs.lib.licenses.mit ];
@@ -960,32 +1008,32 b' self: super: {'
960 1008 };
961 1009 };
962 1010 "paste" = super.buildPythonPackage {
963 name = "paste-2.0.3";
1011 name = "paste-3.0.5";
964 1012 doCheck = false;
965 1013 propagatedBuildInputs = [
966 1014 self."six"
967 1015 ];
968 1016 src = fetchurl {
969 url = "https://files.pythonhosted.org/packages/30/c3/5c2f7c7a02e4f58d4454353fa1c32c94f79fa4e36d07a67c0ac295ea369e/Paste-2.0.3.tar.gz";
970 sha256 = "062jk0nlxf6lb2wwj6zc20rlvrwsnikpkh90y0dn8cjch93s6ii3";
1017 url = "https://files.pythonhosted.org/packages/d4/41/91bde422400786b1b06357c1e6e3a5379f54dc3002aeb337cb767233304e/Paste-3.0.5.tar.gz";
1018 sha256 = "1a6i8fh1fg8r4x800fvy9r82m15clwjim6yf2g9r4dff0y40dchv";
971 1019 };
972 1020 meta = {
973 1021 license = [ pkgs.lib.licenses.mit ];
974 1022 };
975 1023 };
976 1024 "pastedeploy" = super.buildPythonPackage {
977 name = "pastedeploy-1.5.2";
1025 name = "pastedeploy-2.0.1";
978 1026 doCheck = false;
979 1027 src = fetchurl {
980 url = "https://files.pythonhosted.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz";
981 sha256 = "1jz3m4hq8v6hyhfjz9425nd3nvn52cvbfipdcd72krjmla4qz1fm";
1028 url = "https://files.pythonhosted.org/packages/19/a0/5623701df7e2478a68a1b685d1a84518024eef994cde7e4da8449a31616f/PasteDeploy-2.0.1.tar.gz";
1029 sha256 = "02imfbbx1mi2h546f3sr37m47dk9qizaqhzzlhx8bkzxa6fzn8yl";
982 1030 };
983 1031 meta = {
984 1032 license = [ pkgs.lib.licenses.mit ];
985 1033 };
986 1034 };
987 1035 "pastescript" = super.buildPythonPackage {
988 name = "pastescript-2.0.2";
1036 name = "pastescript-3.0.0";
989 1037 doCheck = false;
990 1038 propagatedBuildInputs = [
991 1039 self."paste"
@@ -993,23 +1041,23 b' self: super: {'
993 1041 self."six"
994 1042 ];
995 1043 src = fetchurl {
996 url = "https://files.pythonhosted.org/packages/e5/f0/78e766c3dcc61a4f3a6f71dd8c95168ae9c7a31722b5663d19c1fdf62cb6/PasteScript-2.0.2.tar.gz";
997 sha256 = "1h3nnhn45kf4pbcv669ik4faw04j58k8vbj1hwrc532k0nc28gy0";
1044 url = "https://files.pythonhosted.org/packages/08/2a/3797377a884ab9a064ad4d564ed612e54d26d7997caa8229c9c9df4eac31/PasteScript-3.0.0.tar.gz";
1045 sha256 = "1hvmyz1sbn7ws1syw567ph7km9fi0wi75r3vlyzx6sk0z26xkm6r";
998 1046 };
999 1047 meta = {
1000 1048 license = [ pkgs.lib.licenses.mit ];
1001 1049 };
1002 1050 };
1003 1051 "pathlib2" = super.buildPythonPackage {
1004 name = "pathlib2-2.3.2";
1052 name = "pathlib2-2.3.3";
1005 1053 doCheck = false;
1006 1054 propagatedBuildInputs = [
1007 1055 self."six"
1008 1056 self."scandir"
1009 1057 ];
1010 1058 src = fetchurl {
1011 url = "https://files.pythonhosted.org/packages/db/a8/7d6439c1aec525ed70810abee5b7d7f3aa35347f59bc28343e8f62019aa2/pathlib2-2.3.2.tar.gz";
1012 sha256 = "10yb0iv5x2hs631rcppkhbddx799d3h8pcwmkbh2a66ns3w71ccf";
1059 url = "https://files.pythonhosted.org/packages/bf/d7/a2568f4596b75d2c6e2b4094a7e64f620decc7887f69a1f2811931ea15b9/pathlib2-2.3.3.tar.gz";
1060 sha256 = "0hpp92vqqgcd8h92msm9slv161b1q160igjwnkf2ag6cx0c96695";
1013 1061 };
1014 1062 meta = {
1015 1063 license = [ pkgs.lib.licenses.mit ];
@@ -1084,11 +1132,11 b' self: super: {'
1084 1132 };
1085 1133 };
1086 1134 "pluggy" = super.buildPythonPackage {
1087 name = "pluggy-0.8.0";
1135 name = "pluggy-0.8.1";
1088 1136 doCheck = false;
1089 1137 src = fetchurl {
1090 url = "https://files.pythonhosted.org/packages/65/25/81d0de17cd00f8ca994a4e74e3c4baf7cd25072c0b831dad5c7d9d6138f8/pluggy-0.8.0.tar.gz";
1091 sha256 = "1580p47l2zqzsza8jcnw1h2wh3vvmygk6ly8bvi4w0g8j14sjys4";
1138 url = "https://files.pythonhosted.org/packages/38/e1/83b10c17688af7b2998fa5342fec58ecbd2a5a7499f31e606ae6640b71ac/pluggy-0.8.1.tar.gz";
1139 sha256 = "05l6g42p9ilmabw0hlbiyxy6gyzjri41m5l11a8dzgvi77q35p4d";
1092 1140 };
1093 1141 meta = {
1094 1142 license = [ pkgs.lib.licenses.mit ];
@@ -1110,11 +1158,11 b' self: super: {'
1110 1158 };
1111 1159 };
1112 1160 "psutil" = super.buildPythonPackage {
1113 name = "psutil-5.4.7";
1161 name = "psutil-5.4.8";
1114 1162 doCheck = false;
1115 1163 src = fetchurl {
1116 url = "https://files.pythonhosted.org/packages/7d/9a/1e93d41708f8ed2b564395edfa3389f0fd6d567597401c2e5e2775118d8b/psutil-5.4.7.tar.gz";
1117 sha256 = "0fsgmvzwbdbszkwfnqhib8jcxm4w6zyhvlxlcda0rfm5cyqj4qsv";
1164 url = "https://files.pythonhosted.org/packages/e3/58/0eae6e4466e5abf779d7e2b71fac7fba5f59e00ea36ddb3ed690419ccb0f/psutil-5.4.8.tar.gz";
1165 sha256 = "1hyna338sml2cl1mfb2gs89np18z27mvyhmq4ifh22x07n7mq9kf";
1118 1166 };
1119 1167 meta = {
1120 1168 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1180,25 +1228,25 b' self: super: {'
1180 1228 };
1181 1229 };
1182 1230 "pyasn1" = super.buildPythonPackage {
1183 name = "pyasn1-0.4.4";
1231 name = "pyasn1-0.4.5";
1184 1232 doCheck = false;
1185 1233 src = fetchurl {
1186 url = "https://files.pythonhosted.org/packages/10/46/059775dc8e50f722d205452bced4b3cc965d27e8c3389156acd3b1123ae3/pyasn1-0.4.4.tar.gz";
1187 sha256 = "0drilmx5j25aplfr5wrml0030cs5fgxp9yp94fhllxgx28yjm3zm";
1234 url = "https://files.pythonhosted.org/packages/46/60/b7e32f6ff481b8a1f6c8f02b0fd9b693d1c92ddd2efb038ec050d99a7245/pyasn1-0.4.5.tar.gz";
1235 sha256 = "1xqh3jh2nfi2bflk5a0vn59y3pp1vn54f3ksx652sid92gz2096s";
1188 1236 };
1189 1237 meta = {
1190 1238 license = [ pkgs.lib.licenses.bsdOriginal ];
1191 1239 };
1192 1240 };
1193 1241 "pyasn1-modules" = super.buildPythonPackage {
1194 name = "pyasn1-modules-0.2.2";
1242 name = "pyasn1-modules-0.2.4";
1195 1243 doCheck = false;
1196 1244 propagatedBuildInputs = [
1197 1245 self."pyasn1"
1198 1246 ];
1199 1247 src = fetchurl {
1200 url = "https://files.pythonhosted.org/packages/37/33/74ebdc52be534e683dc91faf263931bc00ae05c6073909fde53999088541/pyasn1-modules-0.2.2.tar.gz";
1201 sha256 = "0ivm850yi7ajjbi8j115qpsj95bgxdsx48nbjzg0zip788c3xkx0";
1248 url = "https://files.pythonhosted.org/packages/bd/a5/ef7bf693e8a8f015386c9167483199f54f8a8ec01d1c737e05524f16e792/pyasn1-modules-0.2.4.tar.gz";
1249 sha256 = "0z3w5dqrrvdplg9ma45j8n23xvyrj9ki8mg4ibqbn7l4qpl90855";
1202 1250 };
1203 1251 meta = {
1204 1252 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1238,30 +1286,16 b' self: super: {'
1238 1286 };
1239 1287 };
1240 1288 "pygments" = super.buildPythonPackage {
1241 name = "pygments-2.3.0";
1289 name = "pygments-2.3.1";
1242 1290 doCheck = false;
1243 1291 src = fetchurl {
1244 url = "https://files.pythonhosted.org/packages/63/a2/91c31c4831853dedca2a08a0f94d788fc26a48f7281c99a303769ad2721b/Pygments-2.3.0.tar.gz";
1245 sha256 = "1z34ms51dh4jq4h3cizp7vd1dmsxcbvffkjsd2xxfav22nn6lrl2";
1292 url = "https://files.pythonhosted.org/packages/64/69/413708eaf3a64a6abb8972644e0f20891a55e621c6759e2c3f3891e05d63/Pygments-2.3.1.tar.gz";
1293 sha256 = "0ji87g09jph8jqcvclgb02qvxasdnr9pzvk90rl66d90yqcxmyjz";
1246 1294 };
1247 1295 meta = {
1248 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 1299 "pymysql" = super.buildPythonPackage {
1266 1300 name = "pymysql-0.8.1";
1267 1301 doCheck = false;
@@ -1285,35 +1319,34 b' self: super: {'
1285 1319 };
1286 1320 };
1287 1321 "pyparsing" = super.buildPythonPackage {
1288 name = "pyparsing-1.5.7";
1322 name = "pyparsing-2.3.0";
1289 1323 doCheck = false;
1290 1324 src = fetchurl {
1291 url = "https://files.pythonhosted.org/packages/6f/2c/47457771c02a8ff0f302b695e094ec309e30452232bd79198ee94fda689f/pyparsing-1.5.7.tar.gz";
1292 sha256 = "17z7ws076z977sclj628fvwrp8y9j2rvdjcsq42v129n1gwi8vk4";
1325 url = "https://files.pythonhosted.org/packages/d0/09/3e6a5eeb6e04467b737d55f8bba15247ac0876f98fae659e58cd744430c6/pyparsing-2.3.0.tar.gz";
1326 sha256 = "14k5v7n3xqw8kzf42x06bzp184spnlkya2dpjyflax6l3yrallzk";
1293 1327 };
1294 1328 meta = {
1295 1329 license = [ pkgs.lib.licenses.mit ];
1296 1330 };
1297 1331 };
1298 1332 "pyramid" = super.buildPythonPackage {
1299 name = "pyramid-1.9.2";
1333 name = "pyramid-1.10.1";
1300 1334 doCheck = false;
1301 1335 propagatedBuildInputs = [
1302 self."setuptools"
1303 self."webob"
1304 self."repoze.lru"
1305 self."zope.interface"
1306 self."zope.deprecation"
1307 self."venusian"
1308 self."translationstring"
1309 self."pastedeploy"
1336 self."hupper"
1310 1337 self."plaster"
1311 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 1347 src = fetchurl {
1315 url = "https://files.pythonhosted.org/packages/a0/c1/b321d07cfc4870541989ad131c86a1d593bfe802af0eca9718a0dadfb97a/pyramid-1.9.2.tar.gz";
1316 sha256 = "09drsl0346nchgxp2j7sa5hlk7mkhfld9wvbd0wicacrp26a92fg";
1348 url = "https://files.pythonhosted.org/packages/0a/3e/22e3ac9be1b70a01139adba8906ee4b8f628bb469fea3c52f6c97b73063c/pyramid-1.10.1.tar.gz";
1349 sha256 = "1h5105nfh6rsrfjiyw20aavyibj36la3hajy6vh1fa77xb4y3hrp";
1317 1350 };
1318 1351 meta = {
1319 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 1370 "pyramid-debugtoolbar" = super.buildPythonPackage {
1338 name = "pyramid-debugtoolbar-4.4";
1371 name = "pyramid-debugtoolbar-4.5";
1339 1372 doCheck = false;
1340 1373 propagatedBuildInputs = [
1341 1374 self."pyramid"
@@ -1345,8 +1378,8 b' self: super: {'
1345 1378 self."ipaddress"
1346 1379 ];
1347 1380 src = fetchurl {
1348 url = "https://files.pythonhosted.org/packages/00/6f/c04eb4e715a7a5a4b24079ab7ffd1dceb1f70b2e24fc17686a2922dbac0a/pyramid_debugtoolbar-4.4.tar.gz";
1349 sha256 = "17p7nxvapvy2hab1rah3ndq2kbs4v83pixj8x2n4m7008ai9lxsz";
1381 url = "https://files.pythonhosted.org/packages/14/28/1f240239af340d19ee271ac62958158c79edb01a44ad8c9885508dd003d2/pyramid_debugtoolbar-4.5.tar.gz";
1382 sha256 = "0x2p3409pnx66n6dx5vc0mk2r1cp1ydr8mp120w44r9pwcngbibl";
1350 1383 };
1351 1384 meta = {
1352 1385 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
@@ -1519,11 +1552,11 b' self: super: {'
1519 1552 };
1520 1553 };
1521 1554 "python-editor" = super.buildPythonPackage {
1522 name = "python-editor-1.0.3";
1555 name = "python-editor-1.0.4";
1523 1556 doCheck = false;
1524 1557 src = fetchurl {
1525 url = "https://files.pythonhosted.org/packages/65/1e/adf6e000ea5dc909aa420352d6ba37f16434c8a3c2fa030445411a1ed545/python-editor-1.0.3.tar.gz";
1526 sha256 = "0rf5xz8vw93v7mhdcvind7fkykipzga430wkcd7wk892xsn6dh53";
1558 url = "https://files.pythonhosted.org/packages/0a/85/78f4a216d28343a67b7397c99825cff336330893f00601443f7c7b2f2234/python-editor-1.0.4.tar.gz";
1559 sha256 = "0yrjh8w72ivqxi4i7xsg5b1vz15x8fg51xra7c3bgfyxqnyadzai";
1527 1560 };
1528 1561 meta = {
1529 1562 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
@@ -1657,7 +1690,7 b' self: super: {'
1657 1690 };
1658 1691 };
1659 1692 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1660 name = "rhodecode-enterprise-ce-4.15.2";
1693 name = "rhodecode-enterprise-ce-4.16.0";
1661 1694 buildInputs = [
1662 1695 self."pytest"
1663 1696 self."py"
@@ -1668,9 +1701,10 b' self: super: {'
1668 1701 self."pytest-timeout"
1669 1702 self."gprof2dot"
1670 1703 self."mock"
1671 self."webtest"
1672 1704 self."cov-core"
1673 1705 self."coverage"
1706 self."webtest"
1707 self."beautifulsoup4"
1674 1708 self."configobj"
1675 1709 ];
1676 1710 doCheck = true;
@@ -1723,7 +1757,6 b' self: super: {'
1723 1757 self."pycrypto"
1724 1758 self."pycurl"
1725 1759 self."pyflakes"
1726 self."pygments-markdown-lexer"
1727 1760 self."pygments"
1728 1761 self."pyparsing"
1729 1762 self."pyramid-beaker"
@@ -1794,9 +1827,10 b' self: super: {'
1794 1827 self."pytest-timeout"
1795 1828 self."gprof2dot"
1796 1829 self."mock"
1797 self."webtest"
1798 1830 self."cov-core"
1799 1831 self."coverage"
1832 self."webtest"
1833 self."beautifulsoup4"
1800 1834 ];
1801 1835 src = ./.;
1802 1836 meta = {
@@ -1804,7 +1838,7 b' self: super: {'
1804 1838 };
1805 1839 };
1806 1840 "rhodecode-tools" = super.buildPythonPackage {
1807 name = "rhodecode-tools-1.0.1";
1841 name = "rhodecode-tools-1.2.1";
1808 1842 doCheck = false;
1809 1843 propagatedBuildInputs = [
1810 1844 self."click"
@@ -1813,14 +1847,16 b' self: super: {'
1813 1847 self."mako"
1814 1848 self."markupsafe"
1815 1849 self."requests"
1816 self."elasticsearch"
1817 self."elasticsearch-dsl"
1818 1850 self."urllib3"
1819 1851 self."whoosh"
1852 self."elasticsearch"
1853 self."elasticsearch-dsl"
1854 self."elasticsearch2"
1855 self."elasticsearch1-dsl"
1820 1856 ];
1821 1857 src = fetchurl {
1822 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.0.1.tar.gz?md5=ffb5d6bcb855305b93cfe23ad42e500b";
1823 sha256 = "0nr300s4sg685qs4wgbwlplwriawrwi6jq79z37frcnpyc89gpvm";
1858 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28";
1859 sha256 = "1k8l3s4mvshza1zay6dfxprq54fyb5dc85dqdva9wa3f466y0adk";
1824 1860 };
1825 1861 meta = {
1826 1862 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
@@ -1864,11 +1900,11 b' self: super: {'
1864 1900 };
1865 1901 };
1866 1902 "setuptools" = super.buildPythonPackage {
1867 name = "setuptools-40.6.2";
1903 name = "setuptools-40.8.0";
1868 1904 doCheck = false;
1869 1905 src = fetchurl {
1870 url = "https://files.pythonhosted.org/packages/b0/d1/8acb42f391cba52e35b131e442e80deffbb8d0676b93261d761b1f0ef8fb/setuptools-40.6.2.zip";
1871 sha256 = "0r2c5hapirlzm34h7pl1lgkm6gk7bcrlrdj28qgsvaqg3f74vfw6";
1906 url = "https://files.pythonhosted.org/packages/c2/f7/c7b501b783e5a74cf1768bc174ee4fb0a8a6ee5af6afa92274ff964703e0/setuptools-40.8.0.zip";
1907 sha256 = "0k9hifpgahnw2a26w3cr346iy733k6d3nwh3f7g9m13y6f8fqkkf";
1872 1908 };
1873 1909 meta = {
1874 1910 license = [ pkgs.lib.licenses.mit ];
@@ -1897,11 +1933,11 b' self: super: {'
1897 1933 };
1898 1934 };
1899 1935 "simplejson" = super.buildPythonPackage {
1900 name = "simplejson-3.11.1";
1936 name = "simplejson-3.16.0";
1901 1937 doCheck = false;
1902 1938 src = fetchurl {
1903 url = "https://files.pythonhosted.org/packages/08/48/c97b668d6da7d7bebe7ea1817a6f76394b0ec959cb04214ca833c34359df/simplejson-3.11.1.tar.gz";
1904 sha256 = "1rr58dppsq73p0qcd9bsw066cdd3v63sqv7j6sqni8frvm4jv8h1";
1939 url = "https://files.pythonhosted.org/packages/e3/24/c35fb1c1c315fc0fffe61ea00d3f88e85469004713dab488dee4f35b0aff/simplejson-3.16.0.tar.gz";
1940 sha256 = "19cws1syk8jzq2pw43878dv6fjkb0ifvjpx0i9aajix6kc9jkwxi";
1905 1941 };
1906 1942 meta = {
1907 1943 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
@@ -1945,25 +1981,25 b' self: super: {'
1945 1981 };
1946 1982 };
1947 1983 "subprocess32" = super.buildPythonPackage {
1948 name = "subprocess32-3.5.2";
1984 name = "subprocess32-3.5.3";
1949 1985 doCheck = false;
1950 1986 src = fetchurl {
1951 url = "https://files.pythonhosted.org/packages/c3/5f/7117737fc7114061837a4f51670d863dd7f7f9c762a6546fa8a0dcfe61c8/subprocess32-3.5.2.tar.gz";
1952 sha256 = "11v62shwmdys48g7ncs3a8jwwnkcl8d4zcwy6dk73z1zy2f9hazb";
1987 url = "https://files.pythonhosted.org/packages/be/2b/beeba583e9877e64db10b52a96915afc0feabf7144dcbf2a0d0ea68bf73d/subprocess32-3.5.3.tar.gz";
1988 sha256 = "1hr5fan8i719hmlmz73hf8rhq74014w07d8ryg7krvvf6692kj3b";
1953 1989 };
1954 1990 meta = {
1955 1991 license = [ pkgs.lib.licenses.psfl ];
1956 1992 };
1957 1993 };
1958 1994 "supervisor" = super.buildPythonPackage {
1959 name = "supervisor-3.3.4";
1995 name = "supervisor-3.3.5";
1960 1996 doCheck = false;
1961 1997 propagatedBuildInputs = [
1962 1998 self."meld3"
1963 1999 ];
1964 2000 src = fetchurl {
1965 url = "https://files.pythonhosted.org/packages/44/60/698e54b4a4a9b956b2d709b4b7b676119c833d811d53ee2500f1b5e96dc3/supervisor-3.3.4.tar.gz";
1966 sha256 = "0wp62z9xprvz2krg02xnbwcnq6pxfq3byd8cxx8c2d8xznih28i1";
2001 url = "https://files.pythonhosted.org/packages/ba/65/92575a8757ed576beaee59251f64a3287bde82bdc03964b89df9e1d29e1b/supervisor-3.3.5.tar.gz";
2002 sha256 = "1w3ahridzbc6rxfpbyx8lij6pjlcgf2ymzyg53llkjqxalp6sk8v";
1967 2003 };
1968 2004 meta = {
1969 2005 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -2059,11 +2095,11 b' self: super: {'
2059 2095 };
2060 2096 };
2061 2097 "urllib3" = super.buildPythonPackage {
2062 name = "urllib3-1.21";
2098 name = "urllib3-1.24.1";
2063 2099 doCheck = false;
2064 2100 src = fetchurl {
2065 url = "https://files.pythonhosted.org/packages/34/95/7b28259d0006ed681c424cd71a668363265eac92b67dddd018eb9a22bff8/urllib3-1.21.tar.gz";
2066 sha256 = "0irnj4wvh2y36s4q3l2vas9qr9m766w6w418nb490j3mf8a8zw6h";
2101 url = "https://files.pythonhosted.org/packages/b1/53/37d82ab391393565f2f831b8eedbffd57db5a718216f82f1a8b4d381a1c1/urllib3-1.24.1.tar.gz";
2102 sha256 = "08lwd9f3hqznyf32vnzwvp87pchx062nkbgyrf67rwlkgj0jk5fy";
2067 2103 };
2068 2104 meta = {
2069 2105 license = [ pkgs.lib.licenses.mit ];
@@ -2081,22 +2117,22 b' self: super: {'
2081 2117 };
2082 2118 };
2083 2119 "venusian" = super.buildPythonPackage {
2084 name = "venusian-1.1.0";
2120 name = "venusian-1.2.0";
2085 2121 doCheck = false;
2086 2122 src = fetchurl {
2087 url = "https://files.pythonhosted.org/packages/38/24/b4b470ab9e0a2e2e9b9030c7735828c8934b4c6b45befd1bb713ec2aeb2d/venusian-1.1.0.tar.gz";
2088 sha256 = "0zapz131686qm0gazwy8bh11vr57pr89jbwbl50s528sqy9f80lr";
2123 url = "https://files.pythonhosted.org/packages/7e/6f/40a9d43ac77cb51cb62be5b5662d170f43f8037bdc4eab56336c4ca92bb7/venusian-1.2.0.tar.gz";
2124 sha256 = "0ghyx66g8ikx9nx1mnwqvdcqm11i1vlq0hnvwl50s48bp22q5v34";
2089 2125 };
2090 2126 meta = {
2091 2127 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2092 2128 };
2093 2129 };
2094 2130 "vine" = super.buildPythonPackage {
2095 name = "vine-1.1.4";
2131 name = "vine-1.2.0";
2096 2132 doCheck = false;
2097 2133 src = fetchurl {
2098 url = "https://files.pythonhosted.org/packages/32/23/36284986e011f3c130d802c3c66abd8f1aef371eae110ddf80c5ae22e1ff/vine-1.1.4.tar.gz";
2099 sha256 = "0wkskb2hb494v9gixqnf4bl972p4ibcmxdykzpwjlfa5picns4aj";
2134 url = "https://files.pythonhosted.org/packages/46/1a/c94317efa98040c5d50fe3cf9080cafb0372ff5afb0283dc018c751c6746/vine-1.2.0.tar.gz";
2135 sha256 = "0xjz2sjbr5jrpjk411b7alkghdskhphgsqqrbi7abqfh2pli6j7f";
2100 2136 };
2101 2137 meta = {
2102 2138 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -2182,18 +2218,18 b' self: super: {'
2182 2218 };
2183 2219 };
2184 2220 "webob" = super.buildPythonPackage {
2185 name = "webob-1.7.4";
2221 name = "webob-1.8.4";
2186 2222 doCheck = false;
2187 2223 src = fetchurl {
2188 url = "https://files.pythonhosted.org/packages/75/34/731e23f52371852dfe7490a61644826ba7fe70fd52a377aaca0f4956ba7f/WebOb-1.7.4.tar.gz";
2189 sha256 = "1na01ljg04z40il7vcrn8g29vaw7nvg1xvhk64cr4jys5wcay44d";
2224 url = "https://files.pythonhosted.org/packages/e4/6c/99e322c3d4cc11d9060a67a9bf2f7c9c581f40988c11fffe89bb8c36bc5e/WebOb-1.8.4.tar.gz";
2225 sha256 = "16cfg5y4n6sihz59vsmns2yqbfm0gfsn3l5xgz2g0pdhilaib0x4";
2190 2226 };
2191 2227 meta = {
2192 2228 license = [ pkgs.lib.licenses.mit ];
2193 2229 };
2194 2230 };
2195 2231 "webtest" = super.buildPythonPackage {
2196 name = "webtest-2.0.29";
2232 name = "webtest-2.0.32";
2197 2233 doCheck = false;
2198 2234 propagatedBuildInputs = [
2199 2235 self."six"
@@ -2202,8 +2238,8 b' self: super: {'
2202 2238 self."beautifulsoup4"
2203 2239 ];
2204 2240 src = fetchurl {
2205 url = "https://files.pythonhosted.org/packages/94/de/8f94738be649997da99c47b104aa3c3984ecec51a1d8153ed09638253d56/WebTest-2.0.29.tar.gz";
2206 sha256 = "0bcj1ica5lnmj5zbvk46x28kgphcsgh7sfnwjmn0cr94mhawrg6v";
2241 url = "https://files.pythonhosted.org/packages/27/9f/9e74449d272ffbef4fb3012e6dbc53c0b24822d545e7a33a342f80131e59/WebTest-2.0.32.tar.gz";
2242 sha256 = "0qp0nnbazzm4ibjiyqfcn6f230svk09i4g58zg2i9x1ga06h48a2";
2207 2243 };
2208 2244 meta = {
2209 2245 license = [ pkgs.lib.licenses.mit ];
@@ -1,12 +1,15 b''
1 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 8 let
7 9 enterprise_ce = import ./default.nix {
8 10 inherit
9 doCheck;
11 doCheck
12 system;
10 13
11 14 # disable checkPhase for build
12 15 checkPhase = ''
@@ -12,7 +12,7 b' bleach==3.0.2'
12 12 celery==4.1.1
13 13 chameleon==2.24
14 14 channelstream==0.5.2
15 click==6.6
15 click==7.0
16 16 colander==1.5.1
17 17 # our custom configobj
18 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 20 decorator==4.1.2
21 21 deform==2.0.7
22 22 docutils==0.14.0
23 dogpile.cache==0.6.7
23 dogpile.cache==0.7.1
24 24 dogpile.core==0.4.1
25 25 ecdsa==0.13
26 26 formencode==1.2.4
@@ -28,42 +28,41 b' future==0.14.3'
28 28 futures==3.0.2
29 29 gnureadline==6.3.8
30 30 infrae.cache==1.0.1
31 iso8601==0.1.11
31 iso8601==0.1.12
32 32 itsdangerous==0.24
33 33 jinja2==2.9.6
34 34 billiard==3.5.0.3
35 kombu==4.2.0
35 kombu==4.2.1
36 36 lxml==4.2.5
37 37 mako==1.0.7
38 38 markdown==2.6.11
39 markupsafe==1.0.0
39 markupsafe==1.1.0
40 40 msgpack-python==0.5.6
41 41 pyotp==2.2.7
42 42 packaging==15.2
43 paste==2.0.3
44 pastedeploy==1.5.2
45 pastescript==2.0.2
46 pathlib2==2.3.2
43 paste==3.0.5
44 pastedeploy==2.0.1
45 pastescript==3.0.0
46 pathlib2==2.3.3
47 47 peppercorn==0.6
48 psutil==5.4.7
48 psutil==5.4.8
49 49 py-bcrypt==0.4
50 50 pycrypto==2.6.1
51 51 pycurl==7.43.0.2
52 52 pyflakes==0.8.1
53 pygments-markdown-lexer==0.1.0.dev39
54 pygments==2.3.0
55 pyparsing==1.5.7
53 pygments==2.3.1
54 pyparsing==2.3.0
56 55 pyramid-beaker==0.8
57 pyramid-debugtoolbar==4.4.0
56 pyramid-debugtoolbar==4.5.0
58 57 pyramid-jinja2==2.7
59 58 pyramid-mako==1.0.2
60 pyramid==1.9.2
59 pyramid==1.10.1
61 60 pyramid_mailer==0.15.1
62 61 python-dateutil
63 62 python-ldap==3.1.0
64 63 python-memcached==1.59
65 64 python-pam==1.8.4
66 python-saml
65 python-saml==2.4.2
67 66 pytz==2018.4
68 67 tzlocal==1.5.1
69 68 pyzmq==14.6.0
@@ -72,21 +71,21 b' redis==2.10.6'
72 71 repoze.lru==0.7
73 72 requests==2.9.1
74 73 routes==2.4.1
75 simplejson==3.11.1
74 simplejson==3.16.0
76 75 six==1.11.0
77 76 sqlalchemy==1.1.18
78 77 sshpubkeys==2.2.0
79 subprocess32==3.5.2
80 supervisor==3.3.4
78 subprocess32==3.5.3
79 supervisor==3.3.5
81 80 tempita==0.5.2
82 81 translationstring==1.3
83 urllib3==1.21
82 urllib3==1.24.1
84 83 urlobject==2.4.3
85 venusian==1.1.0
84 venusian==1.2.0
86 85 weberror==0.10.3
87 86 webhelpers2==2.0
88 87 webhelpers==1.3
89 webob==1.7.4
88 webob==1.8.4
90 89 whoosh==2.7.4
91 90 wsgiref==0.1.2
92 91 zope.cachedescriptors==4.3.1
@@ -113,7 +112,7 b' invoke==0.13.0'
113 112 bumpversion==0.5.3
114 113
115 114 ## http servers
116 gevent==1.3.7
115 gevent==1.4.0
117 116 greenlet==0.4.15
118 117 gunicorn==19.9.0
119 118 waitress==1.1.0
@@ -124,7 +123,7 b' ipdb==0.11.0'
124 123 ipython==5.1.0
125 124
126 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 128 ## appenlight
130 129 appenlight-client==0.6.26
@@ -9,6 +9,8 b' pytest-timeout==1.3.2'
9 9 gprof2dot==2017.9.19
10 10
11 11 mock==1.0.1
12 webtest==2.0.29
13 12 cov-core==1.15.0
14 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 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -18,12 +18,6 b''
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 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 21 import os
28 22 import sys
29 23 import platform
@@ -51,7 +45,7 b' PYRAMID_SETTINGS = {}'
51 45 EXTENSIONS = {}
52 46
53 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 49 __platform__ = platform.system()
56 50 __license__ = 'AGPLv3, and Commercial License'
57 51 __author__ = 'RhodeCode GmbH'
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -21,6 +21,7 b''
21 21 import inspect
22 22 import itertools
23 23 import logging
24 import sys
24 25 import types
25 26 import fnmatch
26 27
@@ -38,6 +39,7 b' from rhodecode.api.exc import ('
38 39 from rhodecode.apps._base import TemplateArgs
39 40 from rhodecode.lib.auth import AuthUser
40 41 from rhodecode.lib.base import get_ip_addr, attach_context_attributes
42 from rhodecode.lib.exc_tracking import store_exception
41 43 from rhodecode.lib.ext_json import json
42 44 from rhodecode.lib.utils2 import safe_str
43 45 from rhodecode.lib.plugins.utils import get_plugin_settings
@@ -140,15 +142,14 b' def jsonrpc_error(request, message, reti'
140 142 def exception_view(exc, request):
141 143 rpc_id = getattr(request, 'rpc_id', None)
142 144
143 fault_message = 'undefined error'
144 145 if isinstance(exc, JSONRPCError):
145 fault_message = exc.message
146 fault_message = safe_str(exc.message)
146 147 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
147 148 elif isinstance(exc, JSONRPCValidationError):
148 149 colander_exc = exc.colander_exception
149 150 # TODO(marcink): think maybe of nicer way to serialize errors ?
150 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 153 elif isinstance(exc, JSONRPCForbidden):
153 154 fault_message = 'Access was denied to this resource.'
154 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 172 fault_message = "No such method: {}. Similar methods: {}".format(
172 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 179 return jsonrpc_error(request, fault_message, rpc_id)
175 180
@@ -292,8 +297,10 b' def request_view(request):'
292 297 raise
293 298 except Exception:
294 299 log.exception('Unhandled exception occurred on api call: %s', func)
295 return jsonrpc_error(request, retid=request.rpc_id,
296 message='Internal server error')
300 exc_info = sys.exc_info()
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 306 def setup_request(request):
@@ -414,8 +421,7 b' def add_jsonrpc_method(config, view, **k'
414 421
415 422 if method is None:
416 423 raise ConfigurationError(
417 'Cannot register a JSON-RPC method without specifying the '
418 '"method"')
424 'Cannot register a JSON-RPC method without specifying the "method"')
419 425
420 426 # we define custom predicate, to enable to detect conflicting methods,
421 427 # those predicates are kind of "translation" from the decorator variables
@@ -524,6 +530,7 b' def includeme(config):'
524 530
525 531 # match filter by given method only
526 532 config.add_view_predicate('jsonrpc_method', MethodPredicate)
533 config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
527 534
528 535 config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer(
529 536 serializer=json.dumps, indent=4))
@@ -538,5 +545,4 b' def includeme(config):'
538 545 config.scan(plugin_module, ignore='rhodecode.api.tests')
539 546 # register some exception handling view
540 547 config.add_view(exception_view, context=JSONRPCBaseError)
541 config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
542 548 config.add_notfound_view(exception_view, jsonrpc_method_not_found=True)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -86,7 +86,9 b' class TestApi(object):'
86 86 def test_api_non_existing_method_have_similar(self, request):
87 87 id_, params = build_data(self.apikey, 'comment', args='xx')
88 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 92 assert_error(id_, expected, given=response.body)
91 93
92 94 def test_api_disabled_user(self, request):
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -38,7 +38,7 b' class TestGetMethod(object):'
38 38 response = api_call(self.app, params)
39 39
40 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 42 assert_ok(id_, expected, given=response.body)
43 43
44 44 def test_get_methods_on_single_match(self):
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -65,6 +65,7 b' class TestGetPullRequest(object):'
65 65 'title': pull_request.title,
66 66 'description': pull_request.description,
67 67 'status': pull_request.status,
68 'state': pull_request.pull_request_state,
68 69 'created_on': pull_request.created_on,
69 70 'updated_on': pull_request.updated_on,
70 71 'commit_ids': pull_request.revisions,
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -59,6 +59,7 b' class TestGetPullRequestComments(object)'
59 59 'status_lbl': 'Under Review'},
60 60 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*',
61 61 'comment_type': 'note',
62 'comment_resolved_by': None,
62 63 'pull_request_version': None}
63 64 ]
64 65 assert_ok(id_, expected, response.body)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestMergePullRequest(object):
32
32 33 @pytest.mark.backends("git", "hg")
33 34 def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications):
34 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 36 pull_request_id = pull_request.pull_request_id
38 37 pull_request_repo = pull_request.target_repo.repo_name
39 38
@@ -46,8 +45,7 b' class TestMergePullRequest(object):'
46 45
47 46 # The above api call detaches the pull request DB object from the
48 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
50 # it.
48 # middleware. Therefore we need to add it back here if we want to use it.
51 49 Session().add(pull_request)
52 50
53 51 expected = 'merge not possible for following reasons: ' \
@@ -55,6 +53,29 b' class TestMergePullRequest(object):'
55 53 assert_error(id_, expected, given=response.body)
56 54
57 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 79 def test_api_merge_pull_request(self, pr_util, no_notifications):
59 80 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
60 81 author = pull_request.user_id
@@ -88,6 +109,7 b' class TestMergePullRequest(object):'
88 109 expected = {
89 110 'executed': True,
90 111 'failure_reason': 0,
112 'merge_status_message': 'This pull request can be automatically merged.',
91 113 'possible': True,
92 114 'merge_commit_id': pull_request.shadow_merge_ref.commit_id,
93 115 'merge_ref': pull_request.shadow_merge_ref._asdict()
@@ -112,6 +134,107 b' class TestMergePullRequest(object):'
112 134 assert_error(id_, expected, given=response.body)
113 135
114 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 238 def test_api_merge_pull_request_repo_error(self, pr_util):
116 239 pull_request = pr_util.create_pull_request()
117 240 id_, params = build_data(
@@ -123,8 +246,7 b' class TestMergePullRequest(object):'
123 246 assert_error(id_, expected, given=response.body)
124 247
125 248 @pytest.mark.backends("git", "hg")
126 def test_api_merge_pull_request_non_admin_with_userid_error(self,
127 pr_util):
249 def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util):
128 250 pull_request = pr_util.create_pull_request(mergeable=True)
129 251 id_, params = build_data(
130 252 self.apikey_regular, 'merge_pull_request',
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 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 44 def assert_ok(id_, expected, given):
32 45 expected = jsonify({
33 46 'id': id_,
@@ -55,8 +68,6 b' def jsonify(obj):'
55 68 def build_data(apikey, method, **kw):
56 69 """
57 70 Builds API data with given random ID
58
59 :param random_id:
60 71 """
61 72 random_id = random.randrange(1, 9999)
62 73 return random_id, json.dumps({
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2014-2018 RhodeCode GmbH
3 # Copyright (C) 2014-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 30 HasPermissionAnyApi, HasRepoPermissionAnyApi, HasRepoGroupPermissionAnyApi)
31 31 from rhodecode.lib.utils import safe_unicode
32 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 34 from rhodecode.lib.utils2 import str2bool
35 35
36 36 log = logging.getLogger(__name__)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2015-2018 RhodeCode GmbH
3 # Copyright (C) 2015-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 26 from rhodecode.api.utils import (
27 27 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
28 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 30 from rhodecode.lib.auth import (HasRepoPermissionAnyApi)
31 31 from rhodecode.lib.base import vcs_operation_context
32 32 from rhodecode.lib.utils2 import str2bool
33 33 from rhodecode.model.changeset_status import ChangesetStatusModel
34 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 36 from rhodecode.model.pull_request import PullRequestModel, MergeCheck
37 37 from rhodecode.model.settings import SettingsModel
38 38 from rhodecode.model.validation_schema import Invalid
@@ -128,16 +128,21 b' def get_pull_request(request, apiuser, p'
128 128 else:
129 129 repo = pull_request.target_repo
130 130
131 if not PullRequestModel().check_user_read(
132 pull_request, apiuser, api=True):
131 if not PullRequestModel().check_user_read(pull_request, apiuser, api=True):
133 132 raise JSONRPCError('repository `%s` or pull request `%s` '
134 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 140 return data
137 141
138 142
139 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 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 156 * ``open``
152 157 * ``closed``
153 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 163 Example output:
156 164
@@ -228,8 +236,10 b' def get_pull_requests(request, apiuser, '
228 236 validate_repo_permissions(apiuser, repoid, repo, _perms)
229 237
230 238 status = Optional.extract(status)
231 pull_requests = PullRequestModel().get_all(repo, statuses=[status])
232 data = [pr.get_api_data() for pr in pull_requests]
239 merge_state = Optional.extract(merge_state, binary=True)
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 243 return data
234 244
235 245
@@ -259,6 +269,7 b' def merge_pull_request('
259 269 "result": {
260 270 "executed": "<bool>",
261 271 "failure_reason": "<int>",
272 "merge_status_message": "<str>",
262 273 "merge_commit_id": "<merge_commit_id>",
263 274 "possible": "<bool>",
264 275 "merge_ref": {
@@ -274,17 +285,25 b' def merge_pull_request('
274 285 repo = get_repo_or_error(repoid)
275 286 else:
276 287 repo = pull_request.target_repo
277
288 auth_user = apiuser
278 289 if not isinstance(userid, Optional):
279 290 if (has_superadmin_permission(apiuser) or
280 291 HasRepoPermissionAnyApi('repository.admin')(
281 292 user=apiuser, repo_name=repo.repo_name)):
282 293 apiuser = get_user_or_error(userid)
294 auth_user = apiuser.AuthUser()
283 295 else:
284 296 raise JSONRPCError('userid is not the same as your user')
285 297
286 check = MergeCheck.validate(
287 pull_request, auth_user=apiuser, translator=request.translate)
298 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
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 307 merge_possible = not check.failed
289 308
290 309 if not merge_possible:
@@ -300,20 +319,20 b' def merge_pull_request('
300 319 target_repo = pull_request.target_repo
301 320 extras = vcs_operation_context(
302 321 request.environ, repo_name=target_repo.repo_name,
303 username=apiuser.username, action='push',
322 username=auth_user.username, action='push',
304 323 scm=target_repo.repo_type)
324 with pull_request.set_state(PullRequest.STATE_UPDATING):
305 325 merge_response = PullRequestModel().merge_repo(
306 326 pull_request, apiuser, extras=extras)
307 327 if merge_response.executed:
308 PullRequestModel().close_pull_request(
309 pull_request.pull_request_id, apiuser)
328 PullRequestModel().close_pull_request(pull_request.pull_request_id, auth_user)
310 329
311 330 Session().commit()
312 331
313 332 # In previous versions the merge response directly contained the merge
314 333 # commit id. It is now contained in the merge reference object. To be
315 334 # backwards compatible we have to extract it again.
316 merge_response = merge_response._asdict()
335 merge_response = merge_response.asdict()
317 336 merge_response['merge_commit_id'] = merge_response['merge_ref'].commit_id
318 337
319 338 return merge_response
@@ -474,14 +493,21 b' def comment_pull_request('
474 493 else:
475 494 repo = pull_request.target_repo
476 495
496 auth_user = apiuser
477 497 if not isinstance(userid, Optional):
478 498 if (has_superadmin_permission(apiuser) or
479 499 HasRepoPermissionAnyApi('repository.admin')(
480 500 user=apiuser, repo_name=repo.repo_name)):
481 501 apiuser = get_user_or_error(userid)
502 auth_user = apiuser.AuthUser()
482 503 else:
483 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 511 if not PullRequestModel().check_user_read(
486 512 pull_request, apiuser, api=True):
487 513 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
@@ -549,7 +575,7 b' def comment_pull_request('
549 575 renderer=renderer,
550 576 comment_type=comment_type,
551 577 resolves_comment_id=resolves_comment_id,
552 auth_user=apiuser
578 auth_user=auth_user
553 579 )
554 580
555 581 if allowed_to_change_status and status:
@@ -589,8 +615,8 b' def comment_pull_request('
589 615 @jsonrpc_method()
590 616 def create_pull_request(
591 617 request, apiuser, source_repo, target_repo, source_ref, target_ref,
592 title=Optional(''), description=Optional(''), description_renderer=Optional(''),
593 reviewers=Optional(None)):
618 owner=Optional(OAttr('apiuser')), title=Optional(''), description=Optional(''),
619 description_renderer=Optional(''), reviewers=Optional(None)):
594 620 """
595 621 Creates a new pull request.
596 622
@@ -611,6 +637,8 b' def create_pull_request('
611 637 :type source_ref: str
612 638 :param target_ref: Set the target ref name.
613 639 :type target_ref: str
640 :param owner: user_id or username
641 :type owner: Optional(str)
614 642 :param title: Optionally Set the pull request title, it's generated otherwise
615 643 :type title: str
616 644 :param description: Set the pull request description.
@@ -634,6 +662,8 b' def create_pull_request('
634 662 _perms = ('repository.admin', 'repository.write', 'repository.read',)
635 663 validate_repo_permissions(apiuser, source_repo, source_db_repo, _perms)
636 664
665 owner = validate_set_owner_permissions(apiuser, owner)
666
637 667 full_source_ref = resolve_ref_or_error(source_ref, source_db_repo)
638 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 710 # recalculate reviewers logic, to make sure we can validate this
681 711 reviewer_rules = get_default_reviewers_data(
682 apiuser.get_instance(), source_db_repo,
712 owner, source_db_repo,
683 713 source_commit, target_db_repo, target_commit)
684 714
685 715 # now MERGE our given with the calculated
@@ -706,7 +736,7 b' def create_pull_request('
706 736 description_renderer = Optional.extract(description_renderer) or default_system_renderer
707 737
708 738 pull_request = PullRequestModel().create(
709 created_by=apiuser.user_id,
739 created_by=owner.user_id,
710 740 source_repo=source_repo,
711 741 source_ref=full_source_ref,
712 742 target_repo=target_repo,
@@ -844,9 +874,16 b' def update_pull_request('
844 874
845 875 commit_changes = {"added": [], "common": [], "removed": []}
846 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 885 if PullRequestModel().has_valid_update_type(pull_request):
848 update_response = PullRequestModel().update_commits(
849 pull_request)
886 update_response = PullRequestModel().update_commits(pull_request)
850 887 commit_changes = update_response.changes or commit_changes
851 888 Session().commit()
852 889
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 29 get_user_group_or_error, get_user_or_error, validate_repo_permissions,
30 30 get_perm_or_error, parse_args, get_origin, build_commit_data,
31 31 validate_set_owner_permissions)
32 from rhodecode.lib import audit_logger
32 from rhodecode.lib import audit_logger, rc_cache
33 33 from rhodecode.lib import repo_maintenance
34 34 from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi
35 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 37 from rhodecode.lib.ext_json import json
38 38 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
39 from rhodecode.lib.vcs import RepositoryError
40 from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError
39 41 from rhodecode.model.changeset_status import ChangesetStatusModel
40 42 from rhodecode.model.comment import CommentsModel
41 43 from rhodecode.model.db import (
@@ -380,7 +382,7 b' def get_repo_changesets(request, apiuser'
380 382
381 383 try:
382 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 386 except TypeError as e:
385 387 raise JSONRPCError(safe_str(e))
386 388 except Exception:
@@ -428,8 +430,8 b' def get_repo_nodes(request, apiuser, rep'
428 430 ``all`` (default), ``files`` and ``dirs``.
429 431 :type ret_type: Optional(str)
430 432 :param details: Returns extended information about nodes, such as
431 md5, binary, and or content. The valid options are ``basic`` and
432 ``full``.
433 md5, binary, and or content.
434 The valid options are ``basic`` and ``full``.
433 435 :type details: Optional(str)
434 436 :param max_file_bytes: Only return file content under this file size bytes
435 437 :type details: Optional(int)
@@ -441,10 +443,15 b' def get_repo_nodes(request, apiuser, rep'
441 443 id : <id_given_in_input>
442 444 result: [
443 445 {
444 "name" : "<name>"
445 "type" : "<type>",
446 "binary": "<true|false>" (only in extended mode)
447 "md5" : "<md5 of file content>" (only in extended mode)
446 "binary": false,
447 "content": "File line\nLine2\n",
448 "extension": "md",
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 461 repo = get_repo_or_error(repoid)
455 462 if not has_superadmin_permission(apiuser):
456 _perms = (
457 'repository.admin', 'repository.write', 'repository.read',)
463 _perms = ('repository.admin', 'repository.write', 'repository.read',)
458 464 validate_repo_permissions(apiuser, repoid, repo, _perms)
459 465
460 466 ret_type = Optional.extract(ret_type)
461 467 details = Optional.extract(details)
462 468 _extended_types = ['basic', 'full']
463 469 if details not in _extended_types:
464 raise JSONRPCError(
465 'ret_type must be one of %s' % (','.join(_extended_types)))
470 raise JSONRPCError('ret_type must be one of %s' % (','.join(_extended_types)))
466 471 extended_info = False
467 472 content = False
468 473 if details == 'basic':
@@ -499,6 +504,149 b' def get_repo_nodes(request, apiuser, rep'
499 504
500 505
501 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 650 def get_repo_refs(request, apiuser, repoid):
503 651 """
504 652 Returns a dictionary of current references. It returns
@@ -1506,6 +1654,73 b' def comment_commit('
1506 1654
1507 1655
1508 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 1724 def grant_user_permission(request, apiuser, repoid, userid, perm):
1510 1725 """
1511 1726 Grant permissions for the specified user on the given repository,
@@ -1543,9 +1758,18 b' def grant_user_permission(request, apius'
1543 1758 _perms = ('repository.admin',)
1544 1759 validate_repo_permissions(apiuser, repoid, repo, _perms)
1545 1760
1761 perm_additions = [[user.user_id, perm.permission_name, "user"]]
1546 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 1774 Session().commit()
1551 1775 return {
@@ -1555,8 +1779,7 b' def grant_user_permission(request, apius'
1555 1779 'success': True
1556 1780 }
1557 1781 except Exception:
1558 log.exception(
1559 "Exception occurred while trying edit permissions for repo")
1782 log.exception("Exception occurred while trying edit permissions for repo")
1560 1783 raise JSONRPCError(
1561 1784 'failed to edit permission for user: `%s` in repo: `%s`' % (
1562 1785 userid, repoid
@@ -1597,8 +1820,19 b' def revoke_user_permission(request, apiu'
1597 1820 _perms = ('repository.admin',)
1598 1821 validate_repo_permissions(apiuser, repoid, repo, _perms)
1599 1822
1823 perm_deletions = [[user.user_id, None, "user"]]
1600 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 1836 Session().commit()
1603 1837 return {
1604 1838 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
@@ -1607,8 +1841,7 b' def revoke_user_permission(request, apiu'
1607 1841 'success': True
1608 1842 }
1609 1843 except Exception:
1610 log.exception(
1611 "Exception occurred while trying revoke permissions to repo")
1844 log.exception("Exception occurred while trying revoke permissions to repo")
1612 1845 raise JSONRPCError(
1613 1846 'failed to edit permission for user: `%s` in repo: `%s`' % (
1614 1847 userid, repoid
@@ -1674,9 +1907,17 b' def grant_user_group_permission(request,'
1674 1907 raise JSONRPCError(
1675 1908 'user group `%s` does not exist' % (usergroupid,))
1676 1909
1910 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
1677 1911 try:
1678 RepoModel().grant_user_group_permission(
1679 repo=repo, group_name=user_group, perm=perm)
1912 changes = RepoModel().update_permissions(
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 1922 Session().commit()
1682 1923 return {
@@ -1739,9 +1980,17 b' def revoke_user_group_permission(request'
1739 1980 raise JSONRPCError(
1740 1981 'user group `%s` does not exist' % (usergroupid,))
1741 1982
1983 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
1742 1984 try:
1743 RepoModel().revoke_user_group_permission(
1744 repo=repo, group_name=user_group)
1985 changes = RepoModel().update_permissions(
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 1995 Session().commit()
1747 1996 return {
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 454 perm_additions = [[user.user_id, perm.permission_name, "user"]]
455 455 try:
456 RepoGroupModel().update_permissions(repo_group=repo_group,
457 perm_additions=perm_additions,
458 recursive=apply_to_children,
459 cur_user=apiuser)
456 changes = RepoGroupModel().update_permissions(
457 repo_group=repo_group, perm_additions=perm_additions,
458 recursive=apply_to_children, 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 469 Session().commit()
461 470 return {
462 471 'msg': 'Granted perm: `%s` (recursive:%s) for user: '
@@ -527,10 +536,19 b' def revoke_user_permission_from_repo_gro'
527 536
528 537 perm_deletions = [[user.user_id, None, "user"]]
529 538 try:
530 RepoGroupModel().update_permissions(repo_group=repo_group,
531 perm_deletions=perm_deletions,
532 recursive=apply_to_children,
533 cur_user=apiuser)
539 changes = RepoGroupModel().update_permissions(
540 repo_group=repo_group, perm_deletions=perm_deletions,
541 recursive=apply_to_children, 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 552 Session().commit()
535 553 return {
536 554 'msg': 'Revoked perm (recursive:%s) for user: '
@@ -611,10 +629,19 b' def grant_user_group_permission_to_repo_'
611 629
612 630 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
613 631 try:
614 RepoGroupModel().update_permissions(repo_group=repo_group,
615 perm_additions=perm_additions,
616 recursive=apply_to_children,
617 cur_user=apiuser)
632 changes = RepoGroupModel().update_permissions(
633 repo_group=repo_group, perm_additions=perm_additions,
634 recursive=apply_to_children, 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 645 Session().commit()
619 646 return {
620 647 'msg': 'Granted perm: `%s` (recursive:%s) '
@@ -694,10 +721,19 b' def revoke_user_group_permission_from_re'
694 721
695 722 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
696 723 try:
697 RepoGroupModel().update_permissions(repo_group=repo_group,
698 perm_deletions=perm_deletions,
699 recursive=apply_to_children,
700 cur_user=apiuser)
724 changes = RepoGroupModel().update_permissions(
725 repo_group=repo_group, perm_deletions=perm_deletions,
726 recursive=apply_to_children, 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 737 Session().commit()
702 738 return {
703 739 'msg': 'Revoked perm (recursive:%s) for user group: '
@@ -716,4 +752,3 b' def revoke_user_group_permission_from_re'
716 752 user_group.users_group_name, repo_group.name
717 753 )
718 754 )
719
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -21,6 +21,9 b''
21 21 import inspect
22 22 import logging
23 23 import itertools
24 import base64
25
26 from pyramid import compat
24 27
25 28 from rhodecode.api import (
26 29 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
@@ -30,10 +33,15 b' from rhodecode.api.utils import ('
30 33 from rhodecode.lib.utils import repo2db_mapper
31 34 from rhodecode.lib import system_info
32 35 from rhodecode.lib import user_sessions
36 from rhodecode.lib import exc_tracking
37 from rhodecode.lib.ext_json import json
33 38 from rhodecode.lib.utils2 import safe_int
34 39 from rhodecode.model.db import UserIpMap
35 40 from rhodecode.model.scm import ScmModel
36 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 46 log = logging.getLogger(__name__)
39 47
@@ -293,7 +301,7 b' def get_method(request, apiuser, pattern'
293 301 :param apiuser: This is filled automatically from the |authtoken|.
294 302 :type apiuser: AuthUser
295 303 :param pattern: pattern to match method names against
296 :type older_then: Optional("*")
304 :type pattern: Optional("*")
297 305
298 306 Example output:
299 307
@@ -349,3 +357,63 b' def get_method(request, apiuser, pattern'
349 357 args_desc.append(func_kwargs)
350 358
351 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 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,6 +19,7 b''
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 from pyramid import compat
22 23
23 24 from rhodecode.api import (
24 25 jsonrpc_method, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
@@ -241,7 +242,7 b' def create_user(request, apiuser, userna'
241 242 # generate temporary password if user is external
242 243 password = PasswordGenerator().gen_password(length=16)
243 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 246 create_repo_group = str2bool(create_repo_group)
246 247
247 248 username = Optional.extract(username)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -22,11 +22,12 b' import time'
22 22 import logging
23 23 import operator
24 24
25 from pyramid import compat
25 26 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPBadRequest
26 27
27 28 from rhodecode.lib import helpers as h, diffs
28 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 31 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
31 32 from rhodecode.model import repo
32 33 from rhodecode.model import repo_group
@@ -249,6 +250,12 b' class RepoAppView(BaseAppView):'
249 250 else: # redirect if we don't show missing requirements
250 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 259 return c
253 260
254 261 def _get_f_path_unchecked(self, matchdict, default=None):
@@ -271,6 +278,13 b' class RepoAppView(BaseAppView):'
271 278 settings = settings_model.get_general_settings()
272 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 289 class PathFilter(object):
276 290
@@ -327,6 +341,13 b' class RepoGroupAppView(BaseAppView):'
327 341 self.db_repo_group = request.db_repo_group
328 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 351 def _revoke_perms_on_yourself(self, form_result):
331 352 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
332 353 form_result['perm_updates'])
@@ -389,7 +410,7 b' class DataGridAppView(object):'
389 410 return draw, start, length
390 411
391 412 def _get_order_col(self, order_by, model):
392 if isinstance(order_by, basestring):
413 if isinstance(order_by, compat.string_types):
393 414 try:
394 415 return operator.attrgetter(order_by)(model)
395 416 except AttributeError:
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -280,8 +280,12 b' def admin_routes(config):'
280 280 pattern='/users/{user_id:\d+}/delete',
281 281 user_route=True)
282 282 config.add_route(
283 name='user_force_password_reset',
284 pattern='/users/{user_id:\d+}/password_reset',
283 name='user_enable_force_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 289 user_route=True)
286 290 config.add_route(
287 291 name='user_create_personal_repo_group',
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 59 ADMIN_PREFIX + '/users/{user_id}/update',
60 60 'user_delete':
61 61 ADMIN_PREFIX + '/users/{user_id}/delete',
62 'user_force_password_reset':
63 ADMIN_PREFIX + '/users/{user_id}/password_reset',
64 62 'user_create_personal_repo_group':
65 63 ADMIN_PREFIX + '/users/{user_id}/create_repo_group',
66 64
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2018-2018 RhodeCode GmbH
3 # Copyright (C) 2018-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -119,8 +119,7 b' class AdminProcessManagementView(BaseApp'
119 119 result = []
120 120
121 121 def on_terminate(proc):
122 msg = "process `PID:{}` terminated with exit code {}".format(
123 proc.pid, proc.returncode or 0)
122 msg = "terminated"
124 123 result.append(msg)
125 124
126 125 procs = []
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -666,8 +666,8 b' class AdminSettingsView(BaseAppView):'
666 666 c = self.load_default_context()
667 667 c.active = 'search'
668 668
669 searcher = searcher_from_config(self.request.registry.settings)
670 c.statistics = searcher.statistics(self.request.translate)
669 c.searcher = searcher_from_config(self.request.registry.settings)
670 c.statistics = c.searcher.statistics(self.request.translate)
671 671
672 672 return self._get_template_context(c)
673 673
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -604,12 +604,9 b' class UsersView(UserAppView):'
604 604 @HasPermissionAllDecorator('hg.admin')
605 605 @CSRFRequired()
606 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 608 renderer='rhodecode:templates/admin/users/user_edit.mako')
609 def user_force_password_reset(self):
610 """
611 toggle reset password flag for this user
612 """
609 def user_enable_force_password_reset(self):
613 610 _ = self.request.translate
614 611 c = self.load_default_context()
615 612
@@ -617,19 +614,41 b' class UsersView(UserAppView):'
617 614 c.user = self.db_user
618 615
619 616 try:
620 old_value = c.user.user_data.get('force_password_change')
621 c.user.update_userdata(force_password_change=not old_value)
617 c.user.update_userdata(force_password_change=True)
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 648 msg = _('Force password change disabled for user')
625 649 audit_logger.store_web(
626 650 'user.edit.password_reset.disabled',
627 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 653 Session().commit()
635 654 h.flash(msg, category='success')
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2013-2018 RhodeCode GmbH
3 # Copyright (C) 2013-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -56,6 +56,10 b' def includeme(config):'
56 56 pattern='/_repos')
57 57
58 58 config.add_route(
59 name='repo_group_list_data',
60 pattern='/_repo_groups')
61
62 config.add_route(
59 63 name='goto_switcher_data',
60 64 pattern='/_goto_data')
61 65
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 31 assert data_item['url']
32 32
33 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 42 elif data_item['type'] == 'repo':
36 43 repos.append(data_item)
37 44 elif data_item['type'] == 'repo_group':
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,7 +19,7 b''
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 # -*- coding: utf-8 -*-
21 21
22 # Copyright (C) 2016-2018 RhodeCode GmbH
22 # Copyright (C) 2016-2019 RhodeCode GmbH
23 23 #
24 24 # This program is free software: you can redistribute it and/or modify
25 25 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -172,7 +172,9 b' class HomeView(BaseAppView):'
172 172 'id': obj.group_name,
173 173 'value': org_query,
174 174 'value_display': obj.group_name,
175 'text': obj.group_name,
175 176 'type': 'repo_group',
177 'repo_group_id': obj.group_id,
176 178 'url': h.route_path(
177 179 'repo_group_home', repo_group_name=obj.group_name)
178 180 }
@@ -246,9 +248,9 b' class HomeView(BaseAppView):'
246 248 }
247 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 252 org_query = query
251 if not query or len(query) < 3:
253 if not query or len(query) < 3 or not searcher:
252 254 return []
253 255
254 256 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
@@ -257,24 +259,34 b' class HomeView(BaseAppView):'
257 259 return []
258 260 commit_hash = commit_hashes[0]
259 261
260 searcher = searcher_from_config(self.request.registry.settings)
261 262 result = searcher.search(
262 'commit_id:%s*' % commit_hash, 'commit', auth_user,
263 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
263 264 raise_on_exc=False)
264 265
265 return [
266 {
266 commits = []
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 275 'id': entry['commit_id'],
268 276 'value': org_query,
269 'value_display': 'repo `{}` commit: {}'.format(
277 'value_display': '`{}` commit: {}'.format(
270 278 entry['repository'], entry['commit_id']),
271 279 'type': 'commit',
272 280 'repo': entry['repository'],
281 'repo_data': repo_data,
282
273 283 'url': h.route_path(
274 284 'repo_commit',
275 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 291 @LoginRequired()
280 292 @view_config(
@@ -305,6 +317,144 b' class HomeView(BaseAppView):'
305 317
306 318 @LoginRequired()
307 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 458 route_name='goto_switcher_data', request_method='GET',
309 459 renderer='json_ext', xhr=True)
310 460 def goto_switcher_data(self):
@@ -315,26 +465,21 b' class HomeView(BaseAppView):'
315 465 query = self.request.GET.get('query')
316 466 log.debug('generating main filter data, query %s', query)
317 467
318 default_search_val = u'Full text search for: `{}`'.format(query)
319 468 res = []
320 469 if not query:
321 470 return {'suggestions': res}
322 471
323 res.append({
324 'id': -1,
325 'value': query,
326 'value_display': default_search_val,
327 'type': 'search',
328 'url': h.route_path(
329 'search', _query={'q': query})
330 })
331 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
472 searcher = searcher_from_config(self.request.registry.settings)
473 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
474 res.append(_q)
475
476 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
332 477 if repo_group_id:
333 478 repo_group = RepoGroup.get(repo_group_id)
334 479 composed_hint = '{}/{}'.format(repo_group.group_name, query)
335 480 show_hint = not query.startswith(repo_group.group_name)
336 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 483 res.append({
339 484 'id': -1,
340 485 'value': composed_hint,
@@ -351,7 +496,7 b' class HomeView(BaseAppView):'
351 496 for serialized_repo in repos:
352 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 500 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
356 501 if allowed_user_search:
357 502 users = self._get_user_list(query)
@@ -362,7 +507,7 b' class HomeView(BaseAppView):'
362 507 for serialized_user_group in user_groups:
363 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 511 if commits:
367 512 unique_repos = collections.OrderedDict()
368 513 for commit in commits:
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 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 130 def test_login_ok_came_from(self):
111 131 test_came_from = '/_admin/users?branch=stable'
112 132 _url = '{}?came_from={}'.format(route_path('login'), test_came_from)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -74,20 +74,17 b' class TestPasswordReset(TestController):'
74 74 'default_password_reset': pwd_reset_setting,
75 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 79 self.logout_user()
79 80
80 81 login_page = self.app.get(route_path('login'))
81 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 84 if show_link:
86 85 asr_login.one_element_exists('a.pwd_reset')
87 asr_index.one_element_exists('a.pwd_reset')
88 86 else:
89 87 asr_login.no_element_exists('a.pwd_reset')
90 asr_index.no_element_exists('a.pwd_reset')
91 88
92 89 response = self.app.get(route_path('reset_password'))
93 90
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -95,6 +95,18 b' def includeme(config):'
95 95 pattern=ADMIN_PREFIX + '/my_account/watched')
96 96
97 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 110 name='my_account_perms',
99 111 pattern=ADMIN_PREFIX + '/my_account/perms')
100 112
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,7 +19,7 b''
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 # -*- coding: utf-8 -*-
21 21
22 # Copyright (C) 2016-2018 RhodeCode GmbH
22 # Copyright (C) 2016-2019 RhodeCode GmbH
23 23 #
24 24 # This program is free software: you can redistribute it and/or modify
25 25 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -20,29 +20,30 b''
20 20
21 21 import logging
22 22 import datetime
23 import string
23 24
24 25 import formencode
25 26 import formencode.htmlfill
27 import peppercorn
26 28 from pyramid.httpexceptions import HTTPFound
27 29 from pyramid.view import view_config
28 from pyramid.renderers import render
29 from pyramid.response import Response
30 30
31 31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 32 from rhodecode import forms
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.lib import audit_logger
35 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 38 from rhodecode.lib.channelstream import (
38 39 channelstream_request, ChannelstreamException)
39 40 from rhodecode.lib.utils2 import safe_int, md5, str2bool
40 41 from rhodecode.model.auth_token import AuthTokenModel
41 42 from rhodecode.model.comment import CommentsModel
42 43 from rhodecode.model.db import (
43 Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload,
44 PullRequest)
45 from rhodecode.model.forms import UserForm, UserExtraEmailForm
44 IntegrityError, joinedload,
45 Repository, UserEmailMap, UserApiKeys, UserFollowing,
46 PullRequest, UserBookmark, RepoGroup)
46 47 from rhodecode.model.meta import Session
47 48 from rhodecode.model.pull_request import PullRequestModel
48 49 from rhodecode.model.scm import RepoList
@@ -392,6 +393,140 b' class MyAccountView(BaseAppView, DataGri'
392 393 @LoginRequired()
393 394 @NotAnonymous()
394 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 530 route_name='my_account_perms', request_method='GET',
396 531 renderer='rhodecode:templates/admin/my_account/my_account.mako')
397 532 def my_account_perms(self):
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -71,6 +71,7 b' class MyAccountSshKeysView(BaseAppView, '
71 71 c = self.load_default_context()
72 72
73 73 c.active = 'ssh_keys_generate'
74 if c.ssh_key_generator_enabled:
74 75 comment = 'RhodeCode-SSH {}'.format(c.user.email or '')
75 76 c.private, c.public = SshKeyModel().generate_keypair(comment=comment)
76 77 c.target_form_url = h.route_path(
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -49,9 +49,13 b' class OpsView(BaseAppView):'
49 49 'instance': self.request.registry.settings.get('instance_id'),
50 50 }
51 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 56 data.update({
53 57 'caller_ip': self.request.user.ip_addr,
54 'caller_name': self.request.user.username,
58 'caller_name': caller_name,
55 59 })
56 60 return {'ok': data}
57 61
@@ -65,11 +69,13 b' class OpsView(BaseAppView):'
65 69 """
66 70 Test exception handling and emails on errors
67 71 """
72
68 73 class TestException(Exception):
69 74 pass
70
75 # add timeout so we add some sort of rate limiter
76 time.sleep(2)
71 77 msg = ('RhodeCode Enterprise test exception. '
72 'Generation time: {}'.format(time.time()))
78 'Client:{}. Generation time: {}.'.format(self.request.user, time.time()))
73 79 raise TestException(msg)
74 80
75 81 @view_config(
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -271,8 +271,8 b' def includeme(config):'
271 271 repo_route=True)
272 272
273 273 config.add_route(
274 name='pullrequest_repo_destinations',
275 pattern='/{repo_name:.*?[^/]}/pull-request/repo-destinations',
274 name='pullrequest_repo_targets',
275 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
276 276 repo_route=True)
277 277
278 278 config.add_route(
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 32 from rhodecode.model.user import UserModel
33 33 from rhodecode.tests import (
34 34 assert_session_flash, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN)
35 from rhodecode.tests.utils import AssertResponse
36 35
37 36
38 37 def route_path(name, params=None, **kwargs):
@@ -45,7 +44,7 b' def route_path(name, params=None, **kwar'
45 44 'pullrequest_show_all': '/{repo_name}/pull-request',
46 45 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
47 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 48 'pullrequest_new': '/{repo_name}/pull-request/new',
50 49 'pullrequest_create': '/{repo_name}/pull-request/create',
51 50 'pullrequest_update': '/{repo_name}/pull-request/{pull_request_id}/update',
@@ -233,8 +232,7 b' class TestPullrequestsView(object):'
233 232 route_path('pullrequest_update',
234 233 repo_name=pull_request.target_repo.repo_name,
235 234 pull_request_id=pull_request_id),
236 params={'update_commits': 'true',
237 'csrf_token': csrf_token})
235 params={'update_commits': 'true', 'csrf_token': csrf_token})
238 236
239 237 expected_msg = str(PullRequestModel.UPDATE_STATUS_MESSAGES[
240 238 UpdateFailureReason.MISSING_SOURCE_REF])
@@ -244,7 +242,8 b' class TestPullrequestsView(object):'
244 242 from rhodecode.lib.vcs.backends.base import MergeFailureReason
245 243 pull_request = pr_util.create_pull_request(
246 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 247 Session().add(pull_request)
249 248 Session().commit()
250 249
@@ -255,12 +254,12 b' class TestPullrequestsView(object):'
255 254 pull_request_id=pull_request_id)
256 255
257 256 response = self.app.get(pull_request_url)
258
259 assertr = AssertResponse(response)
260 expected_msg = PullRequestModel.MERGE_STATUS_MESSAGES[
261 MergeFailureReason.MISSING_TARGET_REF]
262 assertr.element_contains(
263 'span[data-role="merge-message"]', str(expected_msg))
257 target_ref_id = 'invalid-branch'
258 merge_resp = MergeResponse(
259 True, True, '', MergeFailureReason.MISSING_TARGET_REF,
260 metadata={'target_ref': PullRequest.unicode_to_reference(unicode_reference)})
261 response.assert_response().element_contains(
262 'span[data-role="merge-message"]', merge_resp.merge_status_message)
264 263
265 264 def test_comment_and_close_pull_request_custom_message_approved(
266 265 self, pr_util, csrf_token, xhr_header):
@@ -608,8 +607,7 b' class TestPullrequestsView(object):'
608 607
609 608 response = self.app.post(
610 609 route_path('pullrequest_merge',
611 repo_name=repo_name,
612 pull_request_id=pull_request_id),
610 repo_name=repo_name, pull_request_id=pull_request_id),
613 611 params={'csrf_token': csrf_token}).follow()
614 612
615 613 assert response.status_int == 200
@@ -624,10 +622,13 b' class TestPullrequestsView(object):'
624 622 pull_request_id = pull_request.pull_request_id
625 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 629 model_patcher = mock.patch.multiple(
628 630 PullRequestModel,
629 merge_repo=mock.Mock(return_value=MergeResponse(
630 True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)),
631 merge_repo=mock.Mock(return_value=merge_resp),
631 632 merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE')))
632 633
633 634 with model_patcher:
@@ -637,8 +638,10 b' class TestPullrequestsView(object):'
637 638 pull_request_id=pull_request_id),
638 639 params={'csrf_token': csrf_token}, status=302)
639 640
640 assert_session_flash(response, PullRequestModel.MERGE_STATUS_MESSAGES[
641 MergeFailureReason.PUSH_FAILED])
641 merge_resp = MergeResponse(True, True, '', 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 646 def test_update_source_revision(self, backend, csrf_token):
644 647 commits = [
@@ -652,20 +655,20 b' class TestPullrequestsView(object):'
652 655
653 656 # create pr from a in source to A in target
654 657 pull_request = PullRequest()
658
655 659 pull_request.source_repo = source
656 # TODO: johbo: Make sure that we write the source ref this way!
657 660 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
658 661 branch=backend.default_branch_name, commit_id=commit_ids['change'])
662
659 663 pull_request.target_repo = target
660
661 664 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
662 branch=backend.default_branch_name,
663 commit_id=commit_ids['ancestor'])
665 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
666
664 667 pull_request.revisions = [commit_ids['change']]
665 668 pull_request.title = u"Test"
666 669 pull_request.description = u"Description"
667 pull_request.author = UserModel().get_by_username(
668 TEST_USER_ADMIN_LOGIN)
670 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
671 pull_request.pull_request_state = PullRequest.STATE_CREATED
669 672 Session().add(pull_request)
670 673 Session().commit()
671 674 pull_request_id = pull_request.pull_request_id
@@ -676,23 +679,21 b' class TestPullrequestsView(object):'
676 679 # update PR
677 680 self.app.post(
678 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 687 repo_name=target.repo_name,
680 pull_request_id=pull_request_id),
681 params={'update_commits': 'true',
682 'csrf_token': csrf_token})
688 pull_request_id=pull_request.pull_request_id))
689
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 694 # check that we have now both revisions
685 695 pull_request = PullRequest.get(pull_request_id)
686 assert pull_request.revisions == [
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 assert pull_request.revisions == [commit_ids['change-2'], commit_ids['change']]
696 697
697 698 def test_update_target_revision(self, backend, csrf_token):
698 699 commits = [
@@ -707,21 +708,21 b' class TestPullrequestsView(object):'
707 708
708 709 # create pr from a in source to A in target
709 710 pull_request = PullRequest()
711
710 712 pull_request.source_repo = source
711 # TODO: johbo: Make sure that we write the source ref this way!
712 713 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
713 714 branch=backend.default_branch_name, commit_id=commit_ids['change'])
715
714 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 717 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
718 branch=backend.default_branch_name,
719 commit_id=commit_ids['ancestor'])
718 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
719
720 720 pull_request.revisions = [commit_ids['change']]
721 721 pull_request.title = u"Test"
722 722 pull_request.description = u"Description"
723 pull_request.author = UserModel().get_by_username(
724 TEST_USER_ADMIN_LOGIN)
723 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
724 pull_request.pull_request_state = PullRequest.STATE_CREATED
725
725 726 Session().add(pull_request)
726 727 Session().commit()
727 728 pull_request_id = pull_request.pull_request_id
@@ -736,21 +737,19 b' class TestPullrequestsView(object):'
736 737 route_path('pullrequest_update',
737 738 repo_name=target.repo_name,
738 739 pull_request_id=pull_request_id),
739 params={'update_commits': 'true',
740 'csrf_token': csrf_token},
740 params={'update_commits': 'true', 'csrf_token': csrf_token},
741 741 status=200)
742 742
743 743 # check that we have now both revisions
744 744 pull_request = PullRequest.get(pull_request_id)
745 745 assert pull_request.revisions == [commit_ids['change-rebased']]
746 746 assert pull_request.target_ref == 'branch:{branch}:{commit_id}'.format(
747 branch=backend.default_branch_name,
748 commit_id=commit_ids['ancestor-new'])
747 branch=backend.default_branch_name, commit_id=commit_ids['ancestor-new'])
749 748
750 # TODO: johbo: This should be a test on its own
751 response = self.app.get(route_path(
752 'pullrequest_new',
753 repo_name=target.repo_name))
749 response = self.app.get(
750 route_path('pullrequest_show',
751 repo_name=target.repo_name,
752 pull_request_id=pull_request.pull_request_id))
754 753 assert response.status_int == 200
755 754 assert 'Pull request updated to' in response.body
756 755 assert 'with 1 added, 1 removed commits.' in response.body
@@ -772,17 +771,14 b' class TestPullrequestsView(object):'
772 771 # create pr from a in source to A in target
773 772 pull_request = PullRequest()
774 773 pull_request.source_repo = source
775 # TODO: johbo: Make sure that we write the source ref this way!
774
776 775 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
777 776 branch=backend.default_branch_name,
778 777 commit_id=commit_ids['master-commit-3-change-2'])
779 778
780 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 780 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
784 branch=backend.default_branch_name,
785 commit_id=commit_ids['feat-commit-2'])
781 branch=backend.default_branch_name, commit_id=commit_ids['feat-commit-2'])
786 782
787 783 pull_request.revisions = [
788 784 commit_ids['feat-commit-1'],
@@ -790,8 +786,8 b' class TestPullrequestsView(object):'
790 786 ]
791 787 pull_request.title = u"Test"
792 788 pull_request.description = u"Description"
793 pull_request.author = UserModel().get_by_username(
794 TEST_USER_ADMIN_LOGIN)
789 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
790 pull_request.pull_request_state = PullRequest.STATE_CREATED
795 791 Session().add(pull_request)
796 792 Session().commit()
797 793 pull_request_id = pull_request.pull_request_id
@@ -807,13 +803,10 b' class TestPullrequestsView(object):'
807 803 route_path('pullrequest_update',
808 804 repo_name=target.repo_name,
809 805 pull_request_id=pull_request_id),
810 params={'update_commits': 'true',
811 'csrf_token': csrf_token},
806 params={'update_commits': 'true', 'csrf_token': csrf_token},
812 807 status=200)
813 808
814 response = self.app.get(route_path(
815 'pullrequest_new',
816 repo_name=target.repo_name))
809 response = self.app.get(route_path('pullrequest_new', repo_name=target.repo_name))
817 810 assert response.status_int == 200
818 811 response.mustcontain('Pull request updated to')
819 812 response.mustcontain('with 0 added, 0 removed commits.')
@@ -833,21 +826,17 b' class TestPullrequestsView(object):'
833 826 # create pr from a in source to A in target
834 827 pull_request = PullRequest()
835 828 pull_request.source_repo = source
836 # TODO: johbo: Make sure that we write the source ref this way!
829
837 830 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
838 branch=backend.default_branch_name,
839 commit_id=commit_ids['change'])
831 branch=backend.default_branch_name, commit_id=commit_ids['change'])
840 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 833 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
844 branch=backend.default_branch_name,
845 commit_id=commit_ids['ancestor'])
834 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
846 835 pull_request.revisions = [commit_ids['change']]
847 836 pull_request.title = u"Test"
848 837 pull_request.description = u"Description"
849 pull_request.author = UserModel().get_by_username(
850 TEST_USER_ADMIN_LOGIN)
838 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
839 pull_request.pull_request_state = PullRequest.STATE_CREATED
851 840 Session().add(pull_request)
852 841 Session().commit()
853 842 pull_request_id = pull_request.pull_request_id
@@ -860,10 +849,8 b' class TestPullrequestsView(object):'
860 849 # update PR
861 850 self.app.post(
862 851 route_path('pullrequest_update',
863 repo_name=target.repo_name,
864 pull_request_id=pull_request_id),
865 params={'update_commits': 'true',
866 'csrf_token': csrf_token},
852 repo_name=target.repo_name, pull_request_id=pull_request_id),
853 params={'update_commits': 'true', 'csrf_token': csrf_token},
867 854 status=200)
868 855
869 856 # Expect the target reference to be updated correctly
@@ -890,13 +877,12 b' class TestPullrequestsView(object):'
890 877 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
891 878 branch=branch_name, commit_id=commit_ids['new-feature'])
892 879 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
893 branch=backend_git.default_branch_name,
894 commit_id=commit_ids['old-feature'])
880 branch=backend_git.default_branch_name, commit_id=commit_ids['old-feature'])
895 881 pull_request.revisions = [commit_ids['new-feature']]
896 882 pull_request.title = u"Test"
897 883 pull_request.description = u"Description"
898 pull_request.author = UserModel().get_by_username(
899 TEST_USER_ADMIN_LOGIN)
884 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
885 pull_request.pull_request_state = PullRequest.STATE_CREATED
900 886 Session().add(pull_request)
901 887 Session().commit()
902 888
@@ -909,11 +895,11 b' class TestPullrequestsView(object):'
909 895 pull_request_id=pull_request.pull_request_id))
910 896
911 897 assert response.status_int == 200
912 assert_response = AssertResponse(response)
913 assert_response.element_contains(
898
899 response.assert_response().element_contains(
914 900 '#changeset_compare_view_content .alert strong',
915 901 'Missing commits')
916 assert_response.element_contains(
902 response.assert_response().element_contains(
917 903 '#changeset_compare_view_content .alert',
918 904 'This pull request cannot be displayed, because one or more'
919 905 ' commits no longer exist in the source repository.')
@@ -941,15 +927,15 b' class TestPullrequestsView(object):'
941 927 pull_request_id=pull_request.pull_request_id))
942 928
943 929 assert response.status_int == 200
944 assert_response = AssertResponse(response)
945 assert_response.element_contains(
930
931 response.assert_response().element_contains(
946 932 '#changeset_compare_view_content .alert strong',
947 933 'Missing commits')
948 assert_response.element_contains(
934 response.assert_response().element_contains(
949 935 '#changeset_compare_view_content .alert',
950 936 'This pull request cannot be displayed, because one or more'
951 937 ' commits no longer exist in the source repository.')
952 assert_response.element_contains(
938 response.assert_response().element_contains(
953 939 '#update_commits',
954 940 'Update commits')
955 941
@@ -987,8 +973,7 b' class TestPullrequestsView(object):'
987 973 pull_request_id=pull_request.pull_request_id))
988 974
989 975 assert response.status_int == 200
990 assert_response = AssertResponse(response)
991 assert_response.element_contains(
976 response.assert_response().element_contains(
992 977 '#changeset_compare_view_content .alert strong',
993 978 'Missing commits')
994 979
@@ -1004,12 +989,11 b' class TestPullrequestsView(object):'
1004 989 repo_name=pull_request.target_repo.scm_instance().name,
1005 990 pull_request_id=pull_request.pull_request_id))
1006 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 994 origin_children = origin.getchildren()
1011 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 997 target_children = target.getchildren()
1014 998 assert len(target_children) == 1
1015 999
@@ -1038,13 +1022,12 b' class TestPullrequestsView(object):'
1038 1022 repo_name=pull_request.target_repo.scm_instance().name,
1039 1023 pull_request_id=pull_request.pull_request_id))
1040 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 1027 assert origin.text.strip() == 'bookmark: origin'
1045 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 1031 assert target.text.strip() == 'bookmark: target'
1049 1032 assert target.getchildren() == []
1050 1033
@@ -1060,13 +1043,12 b' class TestPullrequestsView(object):'
1060 1043 repo_name=pull_request.target_repo.scm_instance().name,
1061 1044 pull_request_id=pull_request.pull_request_id))
1062 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 1048 assert origin.text.strip() == 'tag: origin'
1067 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 1052 assert target.text.strip() == 'tag: target'
1071 1053 assert target.getchildren() == []
1072 1054
@@ -1090,12 +1072,13 b' class TestPullrequestsView(object):'
1090 1072 repo_name=target_repo.name,
1091 1073 pull_request_id=pr_id))
1092 1074
1093 assertr = AssertResponse(response)
1094 1075 if mergeable:
1095 assertr.element_value_contains('input.pr-mergeinfo', shadow_url)
1096 assertr.element_value_contains('input.pr-mergeinfo ', 'pr-merge')
1076 response.assert_response().element_value_contains(
1077 'input.pr-mergeinfo', shadow_url)
1078 response.assert_response().element_value_contains(
1079 'input.pr-mergeinfo ', 'pr-merge')
1097 1080 else:
1098 assertr.no_element_exists('.pr-mergeinfo')
1081 response.assert_response().no_element_exists('.pr-mergeinfo')
1099 1082
1100 1083
1101 1084 @pytest.mark.usefixtures('app')
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -203,7 +203,6 b' class RepoChangelogView(RepoAppView):'
203 203 pre_load = self._get_preload_attrs()
204 204
205 205 partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR')
206
207 206 try:
208 207 if f_path:
209 208 log.debug('generating changelog for path %s', f_path)
@@ -231,7 +230,7 b' class RepoChangelogView(RepoAppView):'
231 230 else:
232 231 collection = self.rhodecode_vcs_repo.get_commits(
233 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 235 self._load_changelog_data(
237 236 c, collection, p, chunk_size, c.branch_name,
@@ -320,7 +319,8 b' class RepoChangelogView(RepoAppView):'
320 319 collection = list(reversed(collection))
321 320 else:
322 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 325 p = safe_int(self.request.GET.get('page', 1), 1)
326 326 try:
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -97,7 +97,7 b' class RepoCommitsView(RepoAppView):'
97 97 if len(commit_range) == 2:
98 98 commits = self.rhodecode_vcs_repo.get_commits(
99 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 101 commits = list(commits)
102 102 else:
103 103 commits = [self.rhodecode_vcs_repo.get_commit(
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 27 from pyramid.response import Response
28 28
29 29 from rhodecode.apps._base import RepoAppView
30 from rhodecode.controllers.utils import parse_path_ref, get_commit_from_ref_name
30
31 31 from rhodecode.lib import helpers as h
32 32 from rhodecode.lib import diffs, codeblocks
33 33 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
34 34 from rhodecode.lib.utils import safe_str
35 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 37 from rhodecode.lib.vcs.exceptions import (
37 38 EmptyRepositoryError, RepositoryError, RepositoryRequirementError,
38 39 NodeDoesNotExistError)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 34 import rhodecode
35 35 from rhodecode.apps._base import RepoAppView
36 36
37 from rhodecode.controllers.utils import parse_path_ref
37
38 38 from rhodecode.lib import diffs, helpers as h, rc_cache
39 39 from rhodecode.lib import audit_logger
40 from rhodecode.lib.view_utils import parse_path_ref
40 41 from rhodecode.lib.exceptions import NonRelativePathError
41 42 from rhodecode.lib.codeblocks import (
42 43 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
@@ -83,6 +84,7 b' class RepoFilesView(RepoAppView):'
83 84 def load_default_context(self):
84 85 c = self._get_local_tmpl_context(include_app_defaults=True)
85 86 c.rhodecode_repo = self.rhodecode_vcs_repo
87 c.enable_downloads = self.db_repo.enable_downloads
86 88 return c
87 89
88 90 def _ensure_not_locked(self):
@@ -227,10 +229,11 b' class RepoFilesView(RepoAppView):'
227 229 self, c, commit_id, f_path, full_load=False):
228 230
229 231 repo_id = self.db_repo.repo_id
232 force_recache = self.get_recache_flag()
230 233
231 234 cache_seconds = safe_int(
232 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 237 log.debug(
235 238 'Computing FILE TREE for repo_id %s commit_id `%s` and path `%s`'
236 239 'with caching: %s[TTL: %ss]' % (
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -50,8 +50,13 b' class RepoSettingsPermissionsView(RepoAp'
50 50 route_name='edit_repo_perms', request_method='GET',
51 51 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
52 52 def edit_permissions(self):
53 _ = self.request.translate
53 54 c = self.load_default_context()
54 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 60 return self._get_template_context(c)
56 61
57 62 @LoginRequired()
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 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 140 @LoginRequired()
148 141 @HasRepoPermissionAnyDecorator(
149 142 'repository.read', 'repository.write', 'repository.admin')
@@ -272,9 +265,22 b' class RepoPullRequestsView(RepoAppView, '
272 265 route_name='pullrequest_show', request_method='GET',
273 266 renderer='rhodecode:templates/pullrequests/pullrequest_show.mako')
274 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 285 version = self.request.GET.get('version')
280 286 from_version = self.request.GET.get('from_version') or version
@@ -754,7 +760,7 b' class RepoPullRequestsView(RepoAppView, '
754 760
755 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 764 parent_vcs_obj = source_repo.parent.scm_instance()
759 765 if parent_vcs_obj and not parent_vcs_obj.is_empty():
760 766 # change default if we have a parent repo
@@ -811,37 +817,51 b' class RepoPullRequestsView(RepoAppView, '
811 817 @HasRepoPermissionAnyDecorator(
812 818 'repository.read', 'repository.write', 'repository.admin')
813 819 @view_config(
814 route_name='pullrequest_repo_destinations', request_method='GET',
820 route_name='pullrequest_repo_targets', request_method='GET',
815 821 renderer='json_ext', xhr=True)
816 def pull_request_repo_destinations(self):
822 def pullrequest_repo_targets(self):
817 823 _ = self.request.translate
818 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 830 .order_by(func.length(Repository.repo_name)) \
822 .filter(
823 or_(Repository.repo_name == self.db_repo.repo_name,
824 Repository.fork_id == self.db_repo.repo_id))
831 .filter(Repository.fork_id == self.db_repo.parent.repo_id)
825 832
826 833 if filter_query:
827 834 ilike_expression = u'%{}%'.format(safe_unicode(filter_query))
828 query = query.filter(
835 parents_query = parents_query.filter(
829 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
832 if self.db_repo.parent:
833 if filter_query in self.db_repo.parent.repo_name:
834 parent_vcs_obj = self.db_repo.parent.scm_instance()
835 if parent_vcs_obj and not parent_vcs_obj.is_empty():
836 add_parent = True
844 # get other forks, and repo itself
845 query = Repository.query() \
846 .order_by(func.length(Repository.repo_name)) \
847 .filter(
848 or_(Repository.repo_id == self.db_repo.repo_id, # repo itself
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
839 all_repos = query.limit(limit).all()
840 if add_parent:
841 all_repos += [self.db_repo.parent]
853 if filter_query:
854 ilike_expression = u'%{}%'.format(safe_unicode(filter_query))
855 query = query.filter(Repository.repo_name.ilike(ilike_expression))
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 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 865 repos.append({
846 866 'id': obj['name'],
847 867 'text': obj['name'],
@@ -904,12 +924,17 b' class RepoPullRequestsView(RepoAppView, '
904 924 source_db_repo = Repository.get_by_repo_name(_form['source_repo'])
905 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 932 # re-check permissions again here
908 933 # source_repo we must have read permissions
909 934
910 935 source_perm = HasRepoPermissionAny(
911 'repository.read',
912 'repository.write', 'repository.admin')(source_db_repo.repo_name)
936 'repository.read', 'repository.write', 'repository.admin')(
937 source_db_repo.repo_name)
913 938 if not source_perm:
914 939 msg = _('Not Enough permissions to source repo `{}`.'.format(
915 940 source_db_repo.repo_name))
@@ -923,8 +948,8 b' class RepoPullRequestsView(RepoAppView, '
923 948 # target repo we must have read permissions, and also later on
924 949 # we want to check branch permissions here
925 950 target_perm = HasRepoPermissionAny(
926 'repository.read',
927 'repository.write', 'repository.admin')(target_db_repo.repo_name)
951 'repository.read', 'repository.write', 'repository.admin')(
952 target_db_repo.repo_name)
928 953 if not target_perm:
929 954 msg = _('Not Enough permissions to target repo `{}`.'.format(
930 955 target_db_repo.repo_name))
@@ -1027,6 +1052,15 b' class RepoPullRequestsView(RepoAppView, '
1027 1052 h.flash(msg, category='error')
1028 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 1064 # only owner or admin can update it
1031 1065 allowed_to_update = PullRequestModel().check_user_update(
1032 1066 pull_request, self._rhodecode_user)
@@ -1069,6 +1103,8 b' class RepoPullRequestsView(RepoAppView, '
1069 1103
1070 1104 def _update_commits(self, pull_request):
1071 1105 _ = self.request.translate
1106
1107 with pull_request.set_state(PullRequest.STATE_UPDATING):
1072 1108 resp = PullRequestModel().update_commits(pull_request)
1073 1109
1074 1110 if resp.executed:
@@ -1082,8 +1118,7 b' class RepoPullRequestsView(RepoAppView, '
1082 1118 else:
1083 1119 changed = 'nothing'
1084 1120
1085 msg = _(
1086 u'Pull request updated to "{source_commit_id}" with '
1121 msg = _(u'Pull request updated to "{source_commit_id}" with '
1087 1122 u'{count_added} added, {count_removed} removed commits. '
1088 1123 u'Source of changes: {change_source}')
1089 1124 msg = msg.format(
@@ -1094,8 +1129,7 b' class RepoPullRequestsView(RepoAppView, '
1094 1129 h.flash(msg, category='success')
1095 1130
1096 1131 channel = '/repo${}$/pr/{}'.format(
1097 pull_request.target_repo.repo_name,
1098 pull_request.pull_request_id)
1132 pull_request.target_repo.repo_name, pull_request.pull_request_id)
1099 1133 message = msg + (
1100 1134 ' - <a onclick="window.location.reload()">'
1101 1135 '<strong>{}</strong></a>'.format(_('Reload page')))
@@ -1128,8 +1162,23 b' class RepoPullRequestsView(RepoAppView, '
1128 1162 """
1129 1163 pull_request = PullRequest.get_or_404(
1130 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 1179 self.load_default_context()
1180
1181 with pull_request.set_state(PullRequest.STATE_UPDATING):
1133 1182 check = MergeCheck.validate(
1134 1183 pull_request, auth_user=self._rhodecode_user,
1135 1184 translator=self.request.translate)
@@ -1144,6 +1193,7 b' class RepoPullRequestsView(RepoAppView, '
1144 1193 self.request.environ, repo_name=pull_request.target_repo.repo_name,
1145 1194 username=self._rhodecode_db_user.username, action='push',
1146 1195 scm=pull_request.target_repo.repo_type)
1196 with pull_request.set_state(PullRequest.STATE_UPDATING):
1147 1197 self._merge_pull_request(
1148 1198 pull_request, self._rhodecode_db_user, extras)
1149 1199 else:
@@ -1167,10 +1217,8 b' class RepoPullRequestsView(RepoAppView, '
1167 1217 h.flash(msg, category='success')
1168 1218 else:
1169 1219 log.debug(
1170 "The merge was not successful. Merge response: %s",
1171 merge_resp)
1172 msg = PullRequestModel().merge_status_message(
1173 merge_resp.failure_reason)
1220 "The merge was not successful. Merge response: %s", merge_resp)
1221 msg = merge_resp.merge_status_message
1174 1222 h.flash(msg, category='error')
1175 1223
1176 1224 def _update_reviewers(self, pull_request, review_members, reviewer_rules):
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -73,6 +73,8 b' class RepoSettingsView(RepoAppView):'
73 73 'repository.write', 'repository.read', 'repository.admin')(
74 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 78 return self._get_template_context(c)
77 79
78 80 @LoginRequired()
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -24,7 +24,7 b' import rhodecode'
24 24
25 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 28 from rhodecode.apps._base import RepoAppView
29 29 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
30 30 from rhodecode.lib import helpers as h, rc_cache
@@ -141,7 +141,8 b' class RepoSummaryView(RepoAppView):'
141 141
142 142 pre_load = ['author', 'branch', 'date', 'message']
143 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 146 except EmptyRepositoryError:
146 147 collection = self.rhodecode_vcs_repo
147 148
@@ -351,7 +352,7 b' class RepoSummaryView(RepoAppView):'
351 352 return data
352 353
353 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 357 result = []
357 358 for title, refs, ref_type in refs_to_create:
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 29 config.add_route(
30 30 name='search_repo',
31 pattern='/{repo_name:.*?[^/]}/_search', repo_route=True)
32
33 config.add_route(
34 name='search_repo_alt',
31 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 42 # Scan module for configuration decorators.
34 43 config.scan('.views', ignore='.tests')
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -23,8 +23,9 b' import urllib'
23 23 from pyramid.view import view_config
24 24 from webhelpers.util import update_params
25 25
26 from rhodecode.apps._base import BaseAppView, RepoAppView
27 from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
26 from rhodecode.apps._base import BaseAppView, RepoAppView, RepoGroupAppView
27 from rhodecode.lib.auth import (
28 LoginRequired, HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
28 29 from rhodecode.lib.helpers import Page
29 30 from rhodecode.lib.utils2 import safe_str
30 31 from rhodecode.lib.index import searcher_from_config
@@ -34,22 +35,25 b' from rhodecode.model.validation_schema.s'
34 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 39 searcher = searcher_from_config(request.registry.settings)
39 40 formatted_results = []
40 41 execution_time = ''
41 42
42 43 schema = search_schema.SearchParamsSchema()
43
44 search_tags = []
44 45 search_params = {}
45 46 errors = []
46 47 try:
47 48 search_params = schema.deserialize(
48 dict(search_query=request.GET.get('q'),
49 dict(
50 search_query=request.GET.get('q'),
49 51 search_type=request.GET.get('type'),
50 52 search_sort=request.GET.get('sort'),
53 search_max_lines=request.GET.get('max_lines'),
51 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 58 except validation_schema.Invalid as e:
55 59 errors = e.children
@@ -57,20 +61,22 b' def search(request, tmpl_context, repo_n'
57 61 def url_generator(**kw):
58 62 q = urllib.quote(safe_str(search_query))
59 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 67 c = tmpl_context
63 68 search_query = search_params.get('search_query')
64 69 search_type = search_params.get('search_type')
65 70 search_sort = search_params.get('search_sort')
71 search_max_lines = search_params.get('search_max_lines')
66 72 if search_params.get('search_query'):
67 73 page_limit = search_params['page_limit']
68 74 requested_page = search_params['requested_page']
69 75
70 76 try:
71 77 search_result = searcher.search(
72 search_query, search_type, c.auth_user, repo_name,
73 requested_page, page_limit, search_sort)
78 search_query, search_type, c.auth_user, repo_name, repo_group_name,
79 requested_page=requested_page, page_limit=page_limit, sort=search_sort)
74 80
75 81 formatted_results = Page(
76 82 search_result['results'], page=requested_page,
@@ -79,6 +85,8 b' def search(request, tmpl_context, repo_n'
79 85 finally:
80 86 searcher.cleanup()
81 87
88 search_tags = searcher.extract_search_tags(search_query)
89
82 90 if not search_result['error']:
83 91 execution_time = '%s results (%.3f seconds)' % (
84 92 search_result['count'],
@@ -90,6 +98,7 b' def search(request, tmpl_context, repo_n'
90 98
91 99 c.perm_user = c.auth_user
92 100 c.repo_name = repo_name
101 c.repo_group_name = repo_group_name
93 102 c.sort = search_sort
94 103 c.url_generator = url_generator
95 104 c.errors = errors
@@ -98,12 +107,12 b' def search(request, tmpl_context, repo_n'
98 107 c.cur_query = search_query
99 108 c.search_type = search_type
100 109 c.searcher = searcher
110 c.search_tags = search_tags
101 111
102 112
103 113 class SearchView(BaseAppView):
104 114 def load_default_context(self):
105 115 c = self._get_local_tmpl_context()
106
107 116 return c
108 117
109 118 @LoginRequired()
@@ -112,14 +121,14 b' class SearchView(BaseAppView):'
112 121 renderer='rhodecode:templates/search/search.mako')
113 122 def search(self):
114 123 c = self.load_default_context()
115 search(self.request, c, repo_name=None)
124 perform_search(self.request, c)
116 125 return self._get_template_context(c)
117 126
118 127
119 128 class SearchRepoView(RepoAppView):
120 129 def load_default_context(self):
121 130 c = self._get_local_tmpl_context()
122
131 c.active = 'search'
123 132 return c
124 133
125 134 @LoginRequired()
@@ -128,7 +137,28 b' class SearchRepoView(RepoAppView):'
128 137 @view_config(
129 138 route_name='search_repo', request_method='GET',
130 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 143 def search_repo(self):
132 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 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 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 36 _bool_setting(settings, config_keys.generate_authorized_keyfile, 'false')
37 37 _bool_setting(settings, config_keys.wrapper_allow_shell, 'false')
38 38 _bool_setting(settings, config_keys.enable_debug_logging, 'false')
39 _bool_setting(settings, config_keys.ssh_key_generator_enabled, 'true')
39 40
40 41 _string_setting(settings, config_keys.authorized_keys_file_path,
41 42 '~/.ssh/authorized_keys_rhodecode',
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -24,6 +24,7 b''
24 24 generate_authorized_keyfile = 'ssh.generate_authorized_keyfile'
25 25 authorized_keys_file_path = 'ssh.authorized_keys_file_path'
26 26 authorized_keys_line_ssh_opts = 'ssh.authorized_keys_ssh_opts'
27 ssh_key_generator_enabled = 'ssh.enable_ui_key_generator'
27 28 wrapper_cmd = 'ssh.wrapper_cmd'
28 29 wrapper_allow_shell = 'ssh.wrapper_cmd_allow_shell'
29 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -17,10 +17,10 b''
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20 import os
21 21 import logging
22 import os
23 22 import shlex
23 from pyramid import compat
24 24
25 25 # Do not use `from rhodecode import events` here, it will be overridden by the
26 26 # events module in this package due to pythons import mechanism.
@@ -85,6 +85,6 b' def _append_path_sep(path):'
85 85 """
86 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 89 path += os.path.sep
90 90 return path
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 25 import logging
26 26
27 from rhodecode.translation import _
27 import colander
28 28
29 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
29 from rhodecode.translation import _
31 30 from rhodecode.lib.utils2 import safe_str
32 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 37 log = logging.getLogger(__name__)
35 38
@@ -45,6 +48,11 b' class RhodecodeAuthnResource(AuthnPlugin'
45 48
46 49 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
47 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 57 def includeme(self, config):
50 58 config.add_authn_plugin(self)
@@ -64,6 +72,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
64 72 route_name='auth_home',
65 73 context=RhodecodeAuthnResource)
66 74
75 def get_settings_schema(self):
76 return RhodeCodeSettingsSchema()
77
67 78 def get_display_name(self):
68 79 return _('RhodeCode Internal')
69 80
@@ -94,12 +105,36 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
94 105 if not userobj:
95 106 log.debug('userobj was:%s skipping', userobj)
96 107 return None
108
97 109 if userobj.extern_type != self.name:
98 log.warning(
99 "userobj:%s extern_type mismatch got:`%s` expected:`%s`",
110 log.warning("userobj:%s extern_type mismatch got:`%s` expected:`%s`",
100 111 userobj, userobj.extern_type, self.name)
101 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 138 user_attrs = {
104 139 "username": userobj.username,
105 140 "firstname": userobj.firstname,
@@ -131,23 +166,55 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
131 166 user_attrs['_hash_migrate'] = new_hash
132 167
133 168 if userobj.username == User.DEFAULT_USER and userobj.active:
134 log.info(
135 'user `%s` authenticated correctly as anonymous user', userobj.username)
169 log.info('user `%s` authenticated correctly as anonymous user',
170 userobj.username)
136 171 return user_attrs
137 172
138 173 elif userobj.username == username and password_match:
139 174 log.info('user `%s` authenticated correctly', userobj.username)
140 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 177 "authenticating on this plugin", userobj.username)
143 178 return None
144 179 else:
145 log.warning(
146 'user `%s` failed to authenticate via %s, reason: account not '
180 log.warning('user `%s` failed to authenticate via %s, reason: account not '
147 181 'active.', username, self.name)
148 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 218 def includeme(config):
152 219 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
153 220 plugin_factory(plugin_id).includeme(config)
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 25 import logging
26 import colander
26 27
28 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
27 29 from rhodecode.translation import _
28 30 from rhodecode.authentication.base import (
29 31 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
@@ -48,6 +50,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
48 50 Enables usage of authentication tokens for vcs operations.
49 51 """
50 52 uid = 'token'
53 AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs'
51 54
52 55 def includeme(self, config):
53 56 config.add_authn_plugin(self)
@@ -67,6 +70,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
67 70 route_name='auth_home',
68 71 context=RhodecodeAuthnResource)
69 72
73 def get_settings_schema(self):
74 return RhodeCodeSettingsSchema()
75
70 76 def get_display_name(self):
71 77 return _('Rhodecode Token')
72 78
@@ -142,12 +148,10 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
142 148 'user `%s` successfully authenticated via %s',
143 149 user_attrs['username'], self.name)
144 150 return user_attrs
145 log.warn(
146 'user `%s` failed to authenticate via %s, reason: bad or '
151 log.warning('user `%s` failed to authenticate via %s, reason: bad or '
147 152 'inactive token.', username, self.name)
148 153 else:
149 log.warning(
150 'user `%s` failed to authenticate via %s, reason: account not '
154 log.warning('user `%s` failed to authenticate via %s, reason: account not '
151 155 'active.', username, self.name)
152 156 return None
153 157
@@ -155,3 +159,19 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
155 159 def includeme(config):
156 160 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
157 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 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2013-2018 RhodeCode GmbH
3 # Copyright (C) 2013-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 98 global_config = _substitute_values(global_config, environ)
99 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 103 config = Configurator(settings=settings)
104 104
@@ -165,7 +165,7 b' def error_handler(exception, request):'
165 165
166 166 error_explanation = base_response.explanation or str(base_response)
167 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 169 c = AttributeDict()
170 170 c.error_message = base_response.status
171 171 c.error_explanation = error_explanation
@@ -281,6 +281,7 b' def includeme(config):'
281 281 config.include('rhodecode.apps.ops')
282 282 config.include('rhodecode.apps.admin')
283 283 config.include('rhodecode.apps.channelstream')
284 config.include('rhodecode.apps.file_store')
284 285 config.include('rhodecode.apps.login')
285 286 config.include('rhodecode.apps.home')
286 287 config.include('rhodecode.apps.journal')
@@ -381,7 +382,7 b' def wrap_app_in_wsgi_middlewares(pyramid'
381 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 387 Applies settings defaults and does all type conversion.
387 388
@@ -420,6 +421,7 b' def sanitize_settings_and_apply_defaults'
420 421 # TODO: johbo: Re-think this, usually the call to config.include
421 422 # should allow to pass in a prefix.
422 423 settings.setdefault('rhodecode.api.url', '/_admin/api')
424 settings.setdefault('__file__', global_config.get('__file__'))
423 425
424 426 # Sanitize generic settings.
425 427 _list_setting(settings, 'default_encoding', 'UTF-8')
@@ -708,18 +710,29 b' def _string_setting(settings, name, defa'
708 710
709 711
710 712 def _substitute_values(mapping, substitutions):
713 result = {}
711 714
712 715 try:
713 result = {
716 for key, value in mapping.items():
717 # initialize without substitution first
718 result[key] = value
719
714 720 # Note: Cannot use regular replacements, since they would clash
715 721 # with the implementation of ConfigParser. Using "format" instead.
716 key: value.format(**substitutions)
717 for key, value in mapping.items()
718 }
722 try:
723 result[key] = value.format(**substitutions)
719 724 except KeyError as e:
720 raise ValueError(
721 'Failed to substitute env variable: {}. '
722 'Make sure you have specified this env variable without ENV_ prefix'.format(e))
725 env_var = '{}'.format(e.args[0])
726
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 736 except ValueError as e:
724 737 log.warning('Failed to substitute ENV variable: %s', e)
725 738 result = mapping
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -14,19 +14,6 b''
14 14 'hook_type': '',
15 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 17 def _pre_push_hook(*args, **kwargs):
31 18 """
32 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 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 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -7457,7 +7457,7 b' msgid ""'
7457 7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7458 7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7459 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 7461 " {hostname} hostname of this server running RhodeCode,\n"
7462 7462 " {netloc} network location/server host of running RhodeCode server,\n"
7463 7463 " {repo} full repository name,\n"
@@ -7455,7 +7455,7 b' msgid ""'
7455 7455 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7456 7456 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7457 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 7459 " {hostname} hostname of this server running RhodeCode,\n"
7460 7460 " {netloc} network location/server host of running RhodeCode server,\n"
7461 7461 " {repo} full repository name,\n"
@@ -7456,7 +7456,7 b' msgid ""'
7456 7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 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 7460 " {hostname} hostname of this server running RhodeCode,\n"
7461 7461 " {netloc} network location/server host of running RhodeCode server,\n"
7462 7462 " {repo} full repository name,\n"
@@ -7456,7 +7456,7 b' msgid ""'
7456 7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 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 7460 " {hostname} hostname of this server running RhodeCode,\n"
7461 7461 " {netloc} network location/server host of running RhodeCode server,\n"
7462 7462 " {repo} full repository name,\n"
@@ -7463,7 +7463,7 b' msgid ""'
7463 7463 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7464 7464 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7465 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 7467 " {hostname} hostname of this server running RhodeCode,\n"
7468 7468 " {netloc} network location/server host of running RhodeCode server,\n"
7469 7469 " {repo} full repository name,\n"
@@ -7461,7 +7461,7 b' msgid ""'
7461 7461 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7462 7462 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7463 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 7465 " {hostname} hostname of this server running RhodeCode,\n"
7466 7466 " {netloc} network location/server host of running RhodeCode server,\n"
7467 7467 " {repo} full repository name,\n"
@@ -7457,7 +7457,7 b' msgid ""'
7457 7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7458 7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7459 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 7461 " {hostname} hostname of this server running RhodeCode,\n"
7462 7462 " {netloc} network location/server host of running RhodeCode server,\n"
7463 7463 " {repo} full repository name,\n"
@@ -7497,7 +7497,7 b' msgid ""'
7497 7497 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7498 7498 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7499 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 7501 " {hostname} hostname of this server running RhodeCode,\n"
7502 7502 " {netloc} network location/server host of running RhodeCode server,\n"
7503 7503 " {repo} full repository name,\n"
@@ -7474,7 +7474,7 b' msgid ""'
7474 7474 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7475 7475 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7476 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 7478 " {hostname} hostname of this server running RhodeCode,\n"
7479 7479 " {netloc} network location/server host of running RhodeCode server,\n"
7480 7480 " {repo} full repository name,\n"
@@ -7458,7 +7458,7 b' msgid ""'
7458 7458 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7459 7459 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7460 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 7462 " {hostname} hostname of this server running RhodeCode,\n"
7463 7463 " {netloc} network location/server host of running RhodeCode server,\n"
7464 7464 " {repo} full repository name,\n"
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2012-2018 RhodeCode GmbH
2 # Copyright (C) 2012-2019 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -23,17 +23,27 b' import string'
23 23 import collections
24 24 import logging
25 25 import requests
26 import urllib
26 27 from requests.adapters import HTTPAdapter
27 28 from requests.packages.urllib3.util.retry import Retry
28 29
29 30 from mako import exceptions
30 31
32 from rhodecode.lib.utils2 import safe_str
31 33 from rhodecode.translation import _
32 34
33 35
34 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 47 class IntegrationTypeBase(object):
38 48 """ Base class for IntegrationType plugins """
39 49 is_dummy = False
@@ -217,7 +227,9 b' class WebhookDataHandler(CommitParsingDa'
217 227 common_vars.update(extra_vars)
218 228
219 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 234 def repo_push_event_handler(self, event, data):
223 235 url = self.get_base_parsed_template(data)
@@ -228,20 +240,18 b' class WebhookDataHandler(CommitParsingDa'
228 240 if '${branch}' in url or '${branch_head}' in url or '${commit_id}' in url:
229 241 # call it multiple times, for each branch if used in variables
230 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 245 if '${branch_head}' in branch_url:
234 246 # last commit in the aggregate is the head of the branch
235 247 branch_head = commit_ids['branch_head']
236 branch_url = string.Template(branch_url).safe_substitute(
237 branch_head=branch_head)
248 branch_url = UrlTmpl(branch_url).safe_substitute(branch_head=branch_head)
238 249
239 250 # call further down for each commit if used
240 251 if '${commit_id}' in branch_url:
241 252 for commit_data in commit_ids['commits']:
242 253 commit_id = commit_data['raw_id']
243 commit_url = string.Template(branch_url).safe_substitute(
244 commit_id=commit_id)
254 commit_url = UrlTmpl(branch_url).safe_substitute(commit_id=commit_id)
245 255 # register per-commit call
246 256 log.debug(
247 257 'register %s call(%s) to url %s',
@@ -251,36 +261,34 b' class WebhookDataHandler(CommitParsingDa'
251 261
252 262 else:
253 263 # register per-branch call
254 log.debug(
255 'register %s call(%s) to url %s',
264 log.debug('register %s call(%s) to url %s',
256 265 self.name, event, branch_url)
257 url_calls.append(
258 (branch_url, self.headers, data))
266 url_calls.append((branch_url, self.headers, data))
259 267
260 268 else:
261 log.debug(
262 'register %s call(%s) to url %s', self.name, event, url)
269 log.debug('register %s call(%s) to url %s', self.name, event, url)
263 270 url_calls.append((url, self.headers, data))
264 271
265 272 return url_calls
266 273
267 274 def repo_create_event_handler(self, event, data):
268 275 url = self.get_base_parsed_template(data)
269 log.debug(
270 'register %s call(%s) to url %s', self.name, event, url)
276 log.debug('register %s call(%s) to url %s', self.name, event, url)
271 277 return [(url, self.headers, data)]
272 278
273 279 def pull_request_event_handler(self, event, data):
274 280 url = self.get_base_parsed_template(data)
275 log.debug(
276 'register %s call(%s) to url %s', self.name, event, url)
277 url = string.Template(url).safe_substitute(
278 pull_request_id=data['pullrequest']['pull_request_id'],
279 pull_request_title=data['pullrequest']['title'],
280 pull_request_url=data['pullrequest']['url'],
281 pull_request_shadow_url=data['pullrequest']['shadow_url'],
282 pull_request_commits_uid=data['pullrequest']['commits_uid'],
283 )
281 log.debug('register %s call(%s) to url %s', self.name, event, url)
282 pr_vars = [
283 ('pull_request_id', data['pullrequest']['pull_request_id']),
284 ('pull_request_title', data['pullrequest']['title']),
285 ('pull_request_url', data['pullrequest']['url']),
286 ('pull_request_shadow_url', data['pullrequest']['shadow_url']),
287 ('pull_request_commits_uid', data['pullrequest']['commits_uid']),
288 ]
289 for k, v in pr_vars:
290 url = UrlTmpl(url).safe_substitute(**{k: v})
291
284 292 return [(url, self.headers, data)]
285 293
286 294 def __call__(self, event, data):
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -122,8 +122,10 b' class HipchatIntegrationType(Integration'
122 122 log.debug('event not valid: %r', event)
123 123 return
124 124
125 if event.name not in self.settings['events']:
126 log.debug('event ignored: %r', event)
125 allowed_events = self.settings['events']
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 129 return
128 130
129 131 data = event.as_dict()
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -138,8 +138,10 b' class SlackIntegrationType(IntegrationTy'
138 138 log.debug('event not valid: %r', event)
139 139 return
140 140
141 if event.name not in self.settings['events']:
142 log.debug('event ignored: %r', event)
141 allowed_events = self.settings['events']
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 145 return
144 146
145 147 data = event.as_dict()
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -118,12 +118,11 b' class WebhookSettingsSchema(colander.Sch'
118 118 method_type = colander.SchemaNode(
119 119 colander.String(),
120 120 title=_('Call Method'),
121 description=_('Select if the Webhook call should be made '
122 'with POST or GET.'),
121 description=_('Select a HTTP method to use when calling the Webhook.'),
123 122 default='post',
124 123 missing='',
125 124 widget=deform.widget.RadioChoiceWidget(
126 values=[('get', 'GET'), ('post', 'POST')],
125 values=[('get', 'GET'), ('post', 'POST'), ('put', 'PUT')],
127 126 inline=True
128 127 ),
129 128 )
@@ -171,8 +170,10 b' class WebhookIntegrationType(Integration'
171 170 log.debug('event not valid: %r', event)
172 171 return
173 172
174 if event.name not in self.settings['events']:
175 log.debug('event ignored: %r', event)
173 allowed_events = self.settings['events']
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 177 return
177 178
178 179 data = event.as_dict()
@@ -187,8 +188,7 b' class WebhookIntegrationType(Integration'
187 188 handler = WebhookDataHandler(template_url, headers)
188 189
189 190 url_calls = handler(event, data)
190 log.debug('webhook: calling following urls: %s',
191 [x[0] for x in url_calls])
191 log.debug('Webhook: calling following urls: %s', [x[0] for x in url_calls])
192 192
193 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 214 'parents': [{'raw_id': '431b772a5353dad9974b810dd3707d79e3a7f6e0'}],
215 215 'permalink_url': u'http://rc.local:8080/_7/changeset/a815cc738b9651eb5ffbcfb1ce6ccd7c701a5ddf',
216 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 220 'reviewers': [],
219 221 'revision': 9L,
220 222 'short_id': 'a815cc738b96',
@@ -228,11 +230,11 b' def post_to_webhook(url_calls, settings)'
228 230 'url': u'http://rc.local:8080/hg-repo'},
229 231 'server_url': u'http://rc.local:8080',
230 232 'utc_timestamp': datetime.datetime(2017, 11, 30, 13, 0, 1, 569276)
233 }
234 """
231 235
232 """
233 236 call_headers = {
234 'User-Agent': 'RhodeCode-webhook-caller/{}'.format(
235 rhodecode.__version__)
237 'User-Agent': 'RhodeCode-webhook-caller/{}'.format(rhodecode.__version__)
236 238 } # updated below with custom ones, allows override
237 239
238 240 auth = get_auth(settings)
@@ -247,8 +249,7 b' def post_to_webhook(url_calls, settings)'
247 249 headers = headers or {}
248 250 call_headers.update(headers)
249 251
250 log.debug('calling Webhook with method: %s, and auth:%s',
251 call_method, auth)
252 log.debug('calling Webhook with method: %s, and auth:%s', call_method, auth)
252 253 if settings.get('log_data'):
253 254 log.debug('calling webhook with data: %s', data)
254 255 resp = call_method(url, json={
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 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 35 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
36 36
37 37 import rhodecode
38 from rhodecode.apps._base import TemplateArgs
38 39 from rhodecode.authentication.base import VCS_TYPE
39 40 from rhodecode.lib import auth, utils2
40 41 from rhodecode.lib import helpers as h
@@ -43,7 +44,7 b' from rhodecode.lib.exceptions import Use'
43 44 from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes)
44 45 from rhodecode.lib.utils2 import (
45 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 48 from rhodecode.model.notification import NotificationModel
48 49 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
49 50
@@ -281,7 +282,7 b' def get_current_lang(request):'
281 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 287 Attach variables into template context called `c`.
287 288 """
@@ -312,6 +313,10 b' def attach_context_attributes(context, r'
312 313 rc_config.get('rhodecode_dashboard_items', 100))
313 314 context.visual.admin_grid_items = safe_int(
314 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 320 context.visual.repository_fields = str2bool(
316 321 rc_config.get('rhodecode_repository_fields'))
317 322 context.visual.show_version = str2bool(
@@ -343,6 +348,8 b' def attach_context_attributes(context, r'
343 348 config.get('labs_settings_active', 'false'))
344 349 context.ssh_enabled = str2bool(
345 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 354 context.visual.allow_repo_location_change = str2bool(
348 355 config.get('allow_repo_location_change', True))
@@ -417,7 +424,13 b' def attach_context_attributes(context, r'
417 424 context.csrf_token = auth.get_csrf_token(session=request.session)
418 425 context.backends = rhodecode.BACKENDS.keys()
419 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 435 # web case
423 436 if hasattr(request, 'user'):
@@ -551,7 +564,11 b' def bootstrap_request(**kwargs):'
551 564 from rhodecode.lib.partial_renderer import get_partial_renderer
552 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 572 @property
556 573 def call_context(self):
557 574 return self._call_context
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 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
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 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
1 NO CONTENT: file was removed
1 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
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