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

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

@@ -0,0 +1,60 b''
1 .. _user-session-ref:
2
3 Increase User Session Performance
4 ---------------------------------
5
6 The default file-based sessions are only suitable for smaller setups, or
7 instances that doesn't have a lot of users or traffic.
8 They are set as default option because it's setup-free solution.
9
10 The most common issue of file based sessions are file limit errors which occur
11 if there are lots of session files.
12
13 Therefore, in a large scale deployment, to give better performance,
14 scalability, and maintainability we recommend switching from file-based
15 sessions to database-based user sessions or memcached sessions.
16
17 To switch to database-based user sessions uncomment the following section in
18 your :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
19
20
21 .. code-block:: ini
22
23 ## db based session, fast, and allows easy management over logged in users
24 beaker.session.type = ext:database
25 beaker.session.table_name = db_session
26
27 # use just one of the following accoring to the type of database
28 beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
29 beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
30
31 beaker.session.sa.pool_recycle = 3600
32 beaker.session.sa.echo = false
33
34
35 and make sure you comment out the file based sessions.
36
37 .. code-block:: ini
38
39 ## types are file, ext:memcached, ext:database, and memory (default).
40 #beaker.session.type = file
41 #beaker.session.data_dir = %(here)s/data/sessions/data
42
43
44 To switch to memcached-based user sessions uncomment the following section in
45 your :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
46
47 .. code-block:: ini
48
49 ## memcached sessions
50 beaker.session.type = ext:memcached
51 beaker.session.url = localhost:11211
52
53
54 and make sure you comment out the file based sessions.
55
56 .. code-block:: ini
57
58 ## types are file, ext:memcached, ext:database, and memory (default).
59 #beaker.session.type = file
60 #beaker.session.data_dir = %(here)s/data/sessions/data No newline at end of file
@@ -0,0 +1,158 b''
1 |RCE| 4.6.0 |RNS|
2 -----------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2017-02-03
8
9
10 New Features
11 ^^^^^^^^^^^^
12
13 - Pull requests: introduced versioning for pull requests.
14 Each update of pull requests creates and exposes a new version of it.
15 Users can navigate each version to show the previous state of pull request, or
16 generate diffs between versions to show what changed since the last update.
17 Also on each update attached comments are pinned to versions, so users can
18 tell at which state particular comment was made.
19 Various UI/UX fixes on PR page.
20
21 - Pull requests: introduced new merge-checks.
22 Merge checks show nicer UI for the status of merge approval.
23 Merge checks now also forbid a merge if TODO notes are present.
24 Submitting a status will auto-refresh merge checks, it means that it's no
25 longer required to re-load diff to merge a PR.
26 Same logic is now used for API, pre-conditions on show, and checks on
27 actual merge API call.
28
29 - Code review: approval state is now bound to pull request versioning. Users
30 can track their last approval and only show changes of pull requests between
31 their last approval and latest state.
32 - Code review: inline and main comments have now two types. a `note` and `todo`.
33 unresolved TODO comments show up in pull requests or commit view.
34 Unresolved TODO also prevents a PR from being merged.
35 - Code review: added navigation on outdated comments.
36
37 - Diffs: compare mode overhaul.
38 Made compare and commit range pages more consistent with other commit
39 diff pages. Old diff2way is replaced by new diffs with side-by-side
40 mode, and it also removes mergerly. Cleanup button behaviour on the compare
41 page. Switched file-diffs to use the compare page with file filter.
42 Added collapse/expand commits buttons in compare views. Generally improved UX.
43 - Diffs: added a wide-mode button to expand large diffs.
44
45 - Comments: an overhaul of comments forms. Adjust them for new comment types and
46 resolution comments.
47 - Comments: replaced a ctrl+space commands with slash commands. This becomes
48 more standardized and easier to use.
49
50 - Changelog: added load more anchors into changelog view.
51 Users in changelog can now load comments via ajax and extend the data
52 set to show more than 100 commits. This also re-renders the graph. So it's
53 possible to show 1000s of commits in an efficient way with the DAG graph.
54
55 - User sessions: added interface to show, and cleanup user auth sessions.
56 It's possible to show, and clean obsolete sessions. Also a cleanup of all
57 sessions option were added to completely log-out all users from the system.
58
59 - Integrations: webhook integration have now additional setting to choose if
60 the call should be made with POST or GET.
61
62 - API: get_repos call now allows to filter returned data by specifying a start
63 root location. Additionally, a traverse flag was added to define if returned
64 data should be only from top-level or recursive.
65 - API: comment_type (`note` or `todo`) for comment API.
66 - API: added comment_resolved_id into comments API to resolve TODO notes.
67
68
69 General
70 ^^^^^^^
71
72 - Api: comment_pull_request, added commit_id parameter to validate status
73 changed on particular commit. In case users set status on the commit
74 which is not current valid head this API call won't change the status anymore.
75 - Channelstream: added testing panel for live notifications.
76 - Authentication: disable password change form for accounts that are not
77 managed by RhodeCode, in the case of external accounts such as LDAP/oAuth,
78 password reset doesn't make sense.
79 - Core: let pyramid handle tracebacks for all exceptions.
80 Otherwise, we'll miss exception caused in pure pyramid views.
81 - Vcs server: expose remote tracebacks from HTTP backend using
82 the Pyro4AwareFormatter. This will now in most cases propagate VCSServer
83 exception into Enterprise logs for easier tracking of errors
84 - Ishell: updated code with latest iShell changes.
85 - Svn: generate HTTP downgrade via the auto-generated config. This allows
86 a HTTPs/HTTP configuration with SVN.
87 - Dependencies: bumped various pytest related libraries to latest versions.
88 - Dependencies: bumped gevent to 1.1.2 and greenlet to 0.4.10 versions.
89 - Dependencies: bumped msgpack to version 0.4.8.
90 - Dependencies: bumped supervisor to 3.3.1 version.
91 - Dependencies: bumped Whoosh to version 2.7.4.
92 - Dependencies: bumped Markdown library to 2.6.7
93 - Dependencies: bumped mako templates to 1.0.6
94 - Dependencies: bumped waitress version to 1.0.1
95 - Dependencies: bumped pygments to 2.2.0
96 - dependencies: bumped Mercurial version to 4.0.2
97 - dependencies: bumped git version to 2.9.3
98
99
100 Security
101 ^^^^^^^^
102
103 - Login: Don't display partial password helper hash inside the logs.
104 The information is not-required and will prevent people worrying about this
105 shown in logs.
106 - Auth: use pyramid HTTP exception when detecting CSRF errors. It helps
107 catching this error by our error handler and displaying it nicely to users.
108 - SVN: hide password entries in logs using specially generated configuration
109 for Apache Mod-Dav
110 - Permissions: fixed call to correctly check permissions for admin, before admin
111 users were ban deleting of pull requests in certain conditions.
112
113
114 Performance
115 ^^^^^^^^^^^
116
117 - Markup renderer: use global Markdown object to speed up markdown rendering.
118 We'll skip heavy initialization on each render thanks to this.
119 - Diffs: optimize how lexer is fetched for rich highlight mode.
120 Speeds up initial diff creation significantly since lexer cache is re used
121 and we don't need to fetch lexer many times.
122 - VCS: do an early detection of vcs-type request.
123 In case we're handling a VCS request, we can skip some of the pylons
124 stack initialization, speeding the request processing.
125
126
127 Fixes
128 ^^^^^
129
130 - Code review: render outdated comments that don't fit current context.
131 Comments attached to files that were removed from pull-request now will also
132 properly show up.
133 - Markup renderer: don't render plaintext files as RST. This prevents plain
134 Readme files have been wrongly rendered.
135 - VCS: raise a better exception if file node history cannot be extracted.
136 Helps to trace corrupted repositories.
137 - Exception handling: nicer error catching on repository creation.
138 - Fixed excessive number of session object creation. There should be now a
139 significant reduction in new file or DB entries created for sessions.
140 - Core: remove global timezone hook from tests. This was leaking into main
141 application causing TZ problems (such as UTC log dates).
142 - Pull requests: wait for all dynamic checks before enabling opening a PR.
143 This ensures that all code analysis were run before users are allowed to open
144 a pull request.
145 - i18n: use a consistent way of setting user language.
146 - API: added merge checks into API because it was not validated before and could
147 return an error if the merge wasn't possible for some reason.
148 - VCSServer: fetch proper locale before defaulting to default. Prevents
149 errors on some machines that don't have locales set.
150 - VCSServer: fixed 500 error if the wrong URL on HTTP mode vcsserver was accessed.
151
152
153 Upgrade notes
154 ^^^^^^^^^^^^^
155
156 - Integrations: since new POST/GET option was added to integrations, users
157 are advised to optionally check Webhooks integrations and pick one.
158 (default is still POST) No newline at end of file
@@ -0,0 +1,17 b''
1 # test related requirements
2 pytest==3.0.5
3 py==1.4.31
4 pytest-cov==2.4.0
5 pytest-sugar==0.7.1
6 pytest-runner==2.9.0
7 pytest-catchlog==1.2.2
8 pytest-profiling==1.2.2
9 gprof2dot==2016.10.13
10 pytest-timeout==1.2.0
11
12 mock==1.0.1
13 WebTest==1.4.3
14 cov-core==1.15.0
15 coverage==3.7.1
16 cssselect==0.9.1
17 lxml==3.4.4
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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/
@@ -0,0 +1,28 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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 AdminSettingsView(object):
23
24 def __init__(self, context, request):
25 self.request = request
26 self.context = context
27 self.session = request.session
28 self._rhodecode_user = request.user
@@ -0,0 +1,48 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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 collections
22 import logging
23
24 from pylons import tmpl_context as c
25 from pyramid.view import view_config
26
27 from rhodecode.admin.views.base import AdminSettingsView
28 from rhodecode.admin.navigation import navigation_list
29 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
30 from rhodecode.lib.utils import read_opensource_licenses
31
32 log = logging.getLogger(__name__)
33
34
35 class OpenSourceLicensesAdminSettingsView(AdminSettingsView):
36
37 @LoginRequired()
38 @HasPermissionAllDecorator('hg.admin')
39 @view_config(
40 route_name='admin_settings_open_source', request_method='GET',
41 renderer='rhodecode:templates/admin/settings/settings.mako')
42 def open_source_licenses(self):
43 c.active = 'open_source'
44 c.navlist = navigation_list(self.request)
45 c.opensource_licenses = collections.OrderedDict(
46 sorted(read_opensource_licenses().items(), key=lambda t: t[0]))
47
48 return {}
@@ -0,0 +1,100 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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 logging
22
23 from pylons import tmpl_context as c
24 from pyramid.view import view_config
25 from pyramid.httpexceptions import HTTPFound
26
27 from rhodecode.translation import _
28
29 from rhodecode.admin.views.base import AdminSettingsView
30 from rhodecode.lib.auth import (
31 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
32 from rhodecode.lib.utils2 import safe_int
33 from rhodecode.lib import system_info
34 from rhodecode.lib import user_sessions
35
36
37 from rhodecode.admin.navigation import navigation_list
38
39
40 log = logging.getLogger(__name__)
41
42
43 class AdminSessionSettingsView(AdminSettingsView):
44
45 @LoginRequired()
46 @HasPermissionAllDecorator('hg.admin')
47 @view_config(
48 route_name='admin_settings_sessions', request_method='GET',
49 renderer='rhodecode:templates/admin/settings/settings.mako')
50 def settings_sessions(self):
51 c.active = 'sessions'
52 c.navlist = navigation_list(self.request)
53
54 c.cleanup_older_days = 60
55 older_than_seconds = 60 * 60 * 24 * c.cleanup_older_days
56
57 config = system_info.rhodecode_config().get_value()['value']['config']
58 c.session_model = user_sessions.get_session_handler(
59 config.get('beaker.session.type', 'memory'))(config)
60
61 c.session_conf = c.session_model.config
62 c.session_count = c.session_model.get_count()
63 c.session_expired_count = c.session_model.get_expired_count(
64 older_than_seconds)
65
66 return {}
67
68 @LoginRequired()
69 @CSRFRequired()
70 @HasPermissionAllDecorator('hg.admin')
71 @view_config(
72 route_name='admin_settings_sessions_cleanup', request_method='POST')
73 def settings_sessions_cleanup(self):
74 _ = self.request.translate
75 expire_days = safe_int(self.request.params.get('expire_days'))
76
77 if expire_days is None:
78 expire_days = 60
79
80 older_than_seconds = 60 * 60 * 24 * expire_days
81
82 config = system_info.rhodecode_config().get_value()['value']['config']
83 session_model = user_sessions.get_session_handler(
84 config.get('beaker.session.type', 'memory'))(config)
85
86 try:
87 session_model.clean_sessions(
88 older_than_seconds=older_than_seconds)
89 self.request.session.flash(
90 _('Cleaned up old sessions'), queue='success')
91 except user_sessions.CleanupCommand as msg:
92 self.request.session.flash(msg.message, queue='warning')
93 except Exception as e:
94 log.exception('Failed session cleanup')
95 self.request.session.flash(
96 _('Failed to cleanup up old sessions'), queue='error')
97
98 redirect_to = self.request.resource_path(
99 self.context, route_name='admin_settings_sessions')
100 return HTTPFound(redirect_to)
@@ -0,0 +1,60 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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 logging
22
23 from pyramid.view import view_config
24
25 from rhodecode.svn_support.utils import generate_mod_dav_svn_config
26
27 from rhodecode.admin.views.base import AdminSettingsView
28 from rhodecode.lib.auth import (
29 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
30
31 log = logging.getLogger(__name__)
32
33
34 class SvnConfigAdminSettingsView(AdminSettingsView):
35
36 @LoginRequired()
37 @CSRFRequired()
38 @HasPermissionAllDecorator('hg.admin')
39 @view_config(
40 route_name='admin_settings_vcs_svn_generate_cfg',
41 request_method='POST', renderer='json')
42 def vcs_svn_generate_config(self):
43 _ = self.request.translate
44 try:
45 generate_mod_dav_svn_config(self.request.registry)
46 msg = {
47 'message': _('Apache configuration for Subversion generated.'),
48 'level': 'success',
49 }
50 except Exception:
51 log.exception(
52 'Exception while generating the Apache '
53 'configuration for Subversion.')
54 msg = {
55 'message': _('Failed to generate the Apache configuration for Subversion.'),
56 'level': 'error',
57 }
58
59 data = {'message': msg}
60 return data
@@ -0,0 +1,202 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 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 logging
22 import urllib2
23 import packaging.version
24
25 from pylons import tmpl_context as c
26 from pyramid.view import view_config
27
28 import rhodecode
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
31 from rhodecode.lib.utils2 import str2bool
32 from rhodecode.lib import system_info
33 from rhodecode.lib.ext_json import json
34
35 from rhodecode.admin.views.base import AdminSettingsView
36 from rhodecode.admin.navigation import navigation_list
37 from rhodecode.model.settings import SettingsModel
38
39 log = logging.getLogger(__name__)
40
41
42 class AdminSystemInfoSettingsView(AdminSettingsView):
43
44 @staticmethod
45 def get_update_data(update_url):
46 """Return the JSON update data."""
47 ver = rhodecode.__version__
48 log.debug('Checking for upgrade on `%s` server', update_url)
49 opener = urllib2.build_opener()
50 opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
51 response = opener.open(update_url)
52 response_data = response.read()
53 data = json.loads(response_data)
54
55 return data
56
57 def get_update_url(self):
58 settings = SettingsModel().get_all_settings()
59 return settings.get('rhodecode_update_url')
60
61 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
63 @view_config(
64 route_name='admin_settings_system', request_method='GET',
65 renderer='rhodecode:templates/admin/settings/settings.mako')
66 def settings_system_info(self):
67 _ = self.request.translate
68
69 c.active = 'system'
70 c.navlist = navigation_list(self.request)
71
72 # TODO(marcink), figure out how to allow only selected users to do this
73 c.allowed_to_snapshot = self._rhodecode_user.admin
74
75 snapshot = str2bool(self.request.params.get('snapshot'))
76
77 c.rhodecode_update_url = self.get_update_url()
78 server_info = system_info.get_system_info(self.request.environ)
79
80 for key, val in server_info.items():
81 setattr(c, key, val)
82
83 def val(name, subkey='human_value'):
84 return server_info[name][subkey]
85
86 def state(name):
87 return server_info[name]['state']
88
89 def val2(name):
90 val = server_info[name]['human_value']
91 state = server_info[name]['state']
92 return val, state
93
94 update_info_msg = _('Note: please make sure this server can '
95 'access `${url}` for the update link to work',
96 mapping=dict(url=c.rhodecode_update_url))
97 c.data_items = [
98 # update info
99 (_('Update info'), h.literal(
100 '<span class="link" id="check_for_update" >%s.</span>' % (
101 _('Check for updates')) +
102 '<br/> <span >%s.</span>' % (update_info_msg)
103 ), ''),
104
105 # RhodeCode specific
106 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
107 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
108 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
109 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
110 ('', '', ''), # spacer
111
112 # Database
113 (_('Database'), val('database')['url'], state('database')),
114 (_('Database version'), val('database')['version'], state('database')),
115 ('', '', ''), # spacer
116
117 # Platform/Python
118 (_('Platform'), val('platform')['name'], state('platform')),
119 (_('Platform UUID'), val('platform')['uuid'], state('platform')),
120 (_('Python version'), val('python')['version'], state('python')),
121 (_('Python path'), val('python')['executable'], state('python')),
122 ('', '', ''), # spacer
123
124 # Systems stats
125 (_('CPU'), val('cpu'), state('cpu')),
126 (_('Load'), val('load')['text'], state('load')),
127 (_('Memory'), val('memory')['text'], state('memory')),
128 (_('Uptime'), val('uptime')['text'], state('uptime')),
129 ('', '', ''), # spacer
130
131 # Repo storage
132 (_('Storage location'), val('storage')['path'], state('storage')),
133 (_('Storage info'), val('storage')['text'], state('storage')),
134 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
135
136 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
137 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
138
139 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
140 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
141
142 (_('Temp storage location'), val('storage_temp')['path'], state('storage_temp')),
143 (_('Temp storage info'), val('storage_temp')['text'], state('storage_temp')),
144
145 (_('Search info'), val('search')['text'], state('search')),
146 (_('Search location'), val('search')['location'], state('search')),
147 ('', '', ''), # spacer
148
149 # VCS specific
150 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
151 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
152 (_('GIT'), val('git'), state('git')),
153 (_('HG'), val('hg'), state('hg')),
154 (_('SVN'), val('svn'), state('svn')),
155
156 ]
157
158 if snapshot:
159 if c.allowed_to_snapshot:
160 c.data_items.pop(0) # remove server info
161 self.request.override_renderer = 'admin/settings/settings_system_snapshot.mako'
162 else:
163 self.request.session.flash(
164 'You are not allowed to do this', queue='warning')
165 return {}
166
167 @LoginRequired()
168 @HasPermissionAllDecorator('hg.admin')
169 @view_config(
170 route_name='admin_settings_system_update', request_method='GET',
171 renderer='rhodecode:templates/admin/settings/settings_system_update.mako')
172 def settings_system_info_check_update(self):
173 _ = self.request.translate
174
175 update_url = self.get_update_url()
176
177 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
178 try:
179 data = self.get_update_data(update_url)
180 except urllib2.URLError as e:
181 log.exception("Exception contacting upgrade server")
182 self.request.override_renderer = 'string'
183 return _err('Failed to contact upgrade server: %r' % e)
184 except ValueError as e:
185 log.exception("Bad data sent from update server")
186 self.request.override_renderer = 'string'
187 return _err('Bad data sent from update server')
188
189 latest = data['versions'][0]
190
191 c.update_url = update_url
192 c.latest_data = latest
193 c.latest_ver = latest['version']
194 c.cur_ver = rhodecode.__version__
195 c.should_upgrade = False
196
197 if (packaging.version.Version(c.latest_ver) >
198 packaging.version.Version(c.cur_ver)):
199 c.should_upgrade = True
200 c.important_notices = latest['general']
201
202 return {}
@@ -0,0 +1,44 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2017-2017 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 mock
22 import pytest
23
24 from rhodecode.lib.user_sessions import FileAuthSessions
25 from rhodecode.api.tests.utils import (
26 build_data, api_call, assert_ok, assert_error, crash)
27
28
29 @pytest.mark.usefixtures("testuser_api", "app")
30 class TestCleanupSessions(object):
31 def test_api_cleanup_sessions(self):
32 id_, params = build_data(self.apikey, 'cleanup_sessions')
33 response = api_call(self.app, params)
34
35 expected = {'backend': 'file sessions', 'sessions_removed': 0}
36 assert_ok(id_, expected, given=response.body)
37
38 @mock.patch.object(FileAuthSessions, 'clean_sessions', crash)
39 def test_api_cleanup_error(self):
40 id_, params = build_data(self.apikey, 'cleanup_sessions', )
41 response = api_call(self.app, params)
42
43 expected = 'Error occurred during session cleanup'
44 assert_error(id_, expected, given=response.body)
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,6 +1,6 b''
1 1 [bumpversion]
2 current_version = 4.5.2
2 current_version = 4.6.0
3 3 message = release: Bump version {current_version} to {new_version}
4 4
5 5 [bumpversion:file:rhodecode/VERSION]
6 6
@@ -1,33 +1,28 b''
1 1 [DEFAULT]
2 2 done = false
3 3
4 4 [task:bump_version]
5 5 done = true
6 6
7 [task:rc_tools_pinned]
8 done = true
9
10 7 [task:fixes_on_stable]
11 done = true
12 8
13 9 [task:pip2nix_generated]
14 done = true
15 10
16 11 [task:changelog_updated]
17 done = true
18 12
19 13 [task:generate_api_docs]
20 done = true
14
15 [task:updated_translation]
21 16
22 17 [release]
23 state = prepared
24 version = 4.5.2
18 state = in_progress
19 version = 4.6.0
25 20
26 [task:updated_translation]
21 [task:rc_tools_pinned]
27 22
28 23 [task:generate_js_routes]
29 24
30 25 [task:updated_trial_license]
31 26
32 27 [task:generate_oss_licenses]
33 28
@@ -1,55 +1,53 b''
1 1 # top level files
2 2 include test.ini
3 3 include MANIFEST.in
4 4 include README.rst
5 5 include CHANGES.rst
6 6 include LICENSE.txt
7 7
8 8 include rhodecode/VERSION
9 9
10 10 # docs
11 11 recursive-include docs *
12 12
13 13 # all config files
14 14 recursive-include configs *
15 15
16 16 # translations
17 17 recursive-include rhodecode/i18n *
18 18
19 19 # hook templates
20 20 recursive-include rhodecode/config/hook_templates *
21 21
22 22 # non-python core stuff
23 23 recursive-include rhodecode *.cfg
24 24 recursive-include rhodecode *.json
25 25 recursive-include rhodecode *.ini_tmpl
26 26 recursive-include rhodecode *.sh
27 27 recursive-include rhodecode *.mako
28 28
29 29 # 502 page
30 30 include rhodecode/public/502.html
31 31
32 # 502 page
33 include rhodecode/public/502.html
34 32
35 33 # images, css
36 34 include rhodecode/public/css/*.css
37 35 include rhodecode/public/images/*.*
38 36
39 37 # sound files
40 38 include rhodecode/public/sounds/*.mp3
41 39 include rhodecode/public/sounds/*.wav
42 40
43 41 # fonts
44 42 recursive-include rhodecode/public/fonts/ProximaNova *
45 43 recursive-include rhodecode/public/fonts/RCIcons *
46 44
47 45 # js
48 46 recursive-include rhodecode/public/js *
49 47
50 48 # templates
51 49 recursive-include rhodecode/templates *
52 50
53 51 # skip any tests files
54 52 recursive-exclude rhodecode/tests *
55 53
@@ -1,39 +1,35 b''
1
2 .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only web-build
1 3
2 4 WEBPACK=./node_modules/webpack/bin/webpack.js
3 5 GRUNT=grunt
4 6 NODE_PATH=./node_modules
5 CI_PREFIX=enterprise
7
8
9 clean:
10 make test-clean
11 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
6 12
7 .PHONY: docs docs-clean ci-docs clean test test-clean test-lint test-only
13 test:
14 make test-clean
15 make test-only
8 16
17 test-clean:
18 rm -rf coverage.xml htmlcov junit.xml pylint.log result
19 find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
20
21 test-only:
22 PYTHONHASHSEED=random py.test -vv -r xw --cov=rhodecode --cov-report=term-missing --cov-report=html rhodecode
9 23
10 24 docs:
11 25 (cd docs; nix-build default.nix -o result; make clean html)
12 26
13 27 docs-clean:
14 28 (cd docs; make clean)
15 29
16 ci-docs: docs;
17
18
19 clean: test-clean
20 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
21
22 test: test-clean test-only
23
24 test-clean:
25 rm -rf coverage.xml htmlcov junit.xml pylint.log result
26
27 test-only:
28 PYTHONHASHSEED=random py.test -vv -r xw --cov=rhodecode --cov-report=term-missing --cov-report=html rhodecode/tests/
30 docs-cleanup:
31 (cd docs; make cleanup)
29 32
30 33 web-build:
31 34 NODE_PATH=$(NODE_PATH) $(GRUNT)
32 35
33 web-test:
34 @echo "no test for our javascript, yet!"
35
36 docs-bootstrap:
37 (cd docs; nix-build default.nix -o result)
38 @echo "Please go to docs folder and run make html"
39
@@ -1,679 +1,681 b''
1 1
2 2
3 3 ################################################################################
4 4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10
11 11 ################################################################################
12 12 ## EMAIL CONFIGURATION ##
13 13 ## Uncomment and replace with the email address which should receive ##
14 14 ## any error reports after an application crash ##
15 15 ## Additionally these settings will be used by the RhodeCode mailing system ##
16 16 ################################################################################
17 17
18 18 ## prefix all emails subjects with given prefix, helps filtering out emails
19 19 #email_prefix = [RhodeCode]
20 20
21 21 ## email FROM address all mails will be sent
22 22 #app_email_from = rhodecode-noreply@localhost
23 23
24 24 ## Uncomment and replace with the address which should receive any error report
25 25 ## note: using appenlight for error handling doesn't need this to be uncommented
26 26 #email_to = admin@localhost
27 27
28 28 ## in case of Application errors, sent an error email form
29 29 #error_email_from = rhodecode_error@localhost
30 30
31 31 ## additional error message to be send in case of server crash
32 32 #error_message =
33 33
34 34
35 35 #smtp_server = mail.server.com
36 36 #smtp_username =
37 37 #smtp_password =
38 38 #smtp_port =
39 39 #smtp_use_tls = false
40 40 #smtp_use_ssl = true
41 41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
42 42 #smtp_auth =
43 43
44 44 [server:main]
45 45 ## COMMON ##
46 46 host = 127.0.0.1
47 47 port = 5000
48 48
49 49 ##################################
50 50 ## WAITRESS WSGI SERVER ##
51 51 ## Recommended for Development ##
52 52 ##################################
53 53
54 54 use = egg:waitress#main
55 55 ## number of worker threads
56 56 threads = 5
57 57 ## MAX BODY SIZE 100GB
58 58 max_request_body_size = 107374182400
59 59 ## Use poll instead of select, fixes file descriptors limits problems.
60 60 ## May not work on old windows systems.
61 61 asyncore_use_poll = true
62 62
63 63
64 64 ##########################
65 65 ## GUNICORN WSGI SERVER ##
66 66 ##########################
67 67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68 68
69 69 #use = egg:gunicorn#main
70 70 ## Sets the number of process workers. You must set `instance_id = *`
71 71 ## when this option is set to more than one worker, recommended
72 72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
73 73 ## The `instance_id = *` must be set in the [app:main] section below
74 74 #workers = 2
75 75 ## number of threads for each of the worker, must be set to 1 for gevent
76 76 ## generally recommened to be at 1
77 77 #threads = 1
78 78 ## process name
79 79 #proc_name = rhodecode
80 80 ## type of worker class, one of sync, gevent
81 81 ## recommended for bigger setup is using of of other than sync one
82 82 #worker_class = sync
83 83 ## The maximum number of simultaneous clients. Valid only for Gevent
84 84 #worker_connections = 10
85 85 ## max number of requests that worker will handle before being gracefully
86 86 ## restarted, could prevent memory leaks
87 87 #max_requests = 1000
88 88 #max_requests_jitter = 30
89 89 ## amount of time a worker can spend with handling a request before it
90 90 ## gets killed and restarted. Set to 6hrs
91 91 #timeout = 21600
92 92
93 93
94 94 ## prefix middleware for RhodeCode.
95 95 ## recommended when using proxy setup.
96 96 ## allows to set RhodeCode under a prefix in server.
97 97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
98 98 ## And set your prefix like: `prefix = /custom_prefix`
99 99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
100 100 ## to make your cookies only work on prefix url
101 101 [filter:proxy-prefix]
102 102 use = egg:PasteDeploy#prefix
103 103 prefix = /
104 104
105 105 [app:main]
106 106 use = egg:rhodecode-enterprise-ce
107 107
108 108 ## enable proxy prefix middleware, defined above
109 109 #filter-with = proxy-prefix
110 110
111 111 # During development the we want to have the debug toolbar enabled
112 112 pyramid.includes =
113 113 pyramid_debugtoolbar
114 114 rhodecode.utils.debugtoolbar
115 115 rhodecode.lib.middleware.request_wrapper
116 116
117 117 pyramid.reload_templates = true
118 118
119 119 debugtoolbar.hosts = 0.0.0.0/0
120 120 debugtoolbar.exclude_prefixes =
121 121 /css
122 122 /fonts
123 123 /images
124 124 /js
125 125
126 126 ## RHODECODE PLUGINS ##
127 127 rhodecode.includes =
128 128 rhodecode.api
129 129
130 130
131 131 # api prefix url
132 132 rhodecode.api.url = /_admin/api
133 133
134 134
135 135 ## END RHODECODE PLUGINS ##
136 136
137 137 ## encryption key used to encrypt social plugin tokens,
138 138 ## remote_urls with credentials etc, if not set it defaults to
139 139 ## `beaker.session.secret`
140 140 #rhodecode.encrypted_values.secret =
141 141
142 142 ## decryption strict mode (enabled by default). It controls if decryption raises
143 143 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
144 144 #rhodecode.encrypted_values.strict = false
145 145
146 146 ## return gzipped responses from Rhodecode (static files/application)
147 147 gzip_responses = false
148 148
149 149 ## autogenerate javascript routes file on startup
150 150 generate_js_files = false
151 151
152 152 ## Optional Languages
153 153 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
154 154 lang = en
155 155
156 156 ## perform a full repository scan on each server start, this should be
157 157 ## set to false after first startup, to allow faster server restarts.
158 158 startup.import_repos = false
159 159
160 160 ## Uncomment and set this path to use archive download cache.
161 161 ## Once enabled, generated archives will be cached at this location
162 162 ## and served from the cache during subsequent requests for the same archive of
163 163 ## the repository.
164 164 #archive_cache_dir = /tmp/tarballcache
165 165
166 166 ## change this to unique ID for security
167 167 app_instance_uuid = rc-production
168 168
169 169 ## cut off limit for large diffs (size in bytes)
170 170 cut_off_limit_diff = 1024000
171 171 cut_off_limit_file = 256000
172 172
173 173 ## use cache version of scm repo everywhere
174 174 vcs_full_cache = true
175 175
176 176 ## force https in RhodeCode, fixes https redirects, assumes it's always https
177 177 ## Normally this is controlled by proper http flags sent from http server
178 178 force_https = false
179 179
180 180 ## use Strict-Transport-Security headers
181 181 use_htsts = false
182 182
183 183 ## number of commits stats will parse on each iteration
184 184 commit_parse_limit = 25
185 185
186 186 ## git rev filter option, --all is the default filter, if you need to
187 187 ## hide all refs in changelog switch this to --branches --tags
188 188 git_rev_filter = --branches --tags
189 189
190 190 # Set to true if your repos are exposed using the dumb protocol
191 191 git_update_server_info = false
192 192
193 193 ## RSS/ATOM feed options
194 194 rss_cut_off_limit = 256000
195 195 rss_items_per_page = 10
196 196 rss_include_diff = false
197 197
198 198 ## gist URL alias, used to create nicer urls for gist. This should be an
199 199 ## url that does rewrites to _admin/gists/{gistid}.
200 200 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
201 201 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
202 202 gist_alias_url =
203 203
204 204 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
205 205 ## used for access.
206 206 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
207 207 ## came from the the logged in user who own this authentication token.
208 208 ##
209 209 ## Syntax is ControllerClass:function_pattern.
210 210 ## To enable access to raw_files put `FilesController:raw`.
211 211 ## To enable access to patches add `ChangesetController:changeset_patch`.
212 212 ## The list should be "," separated and on a single line.
213 213 ##
214 214 ## Recommended controllers to enable:
215 215 # ChangesetController:changeset_patch,
216 216 # ChangesetController:changeset_raw,
217 217 # FilesController:raw,
218 218 # FilesController:archivefile,
219 219 # GistsController:*,
220 220 api_access_controllers_whitelist =
221 221
222 222 ## default encoding used to convert from and to unicode
223 223 ## can be also a comma separated list of encoding in case of mixed encodings
224 224 default_encoding = UTF-8
225 225
226 226 ## instance-id prefix
227 227 ## a prefix key for this instance used for cache invalidation when running
228 228 ## multiple instances of rhodecode, make sure it's globally unique for
229 229 ## all running rhodecode instances. Leave empty if you don't use it
230 230 instance_id =
231 231
232 232 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
233 233 ## of an authentication plugin also if it is disabled by it's settings.
234 234 ## This could be useful if you are unable to log in to the system due to broken
235 235 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
236 236 ## module to log in again and fix the settings.
237 237 ##
238 238 ## Available builtin plugin IDs (hash is part of the ID):
239 239 ## egg:rhodecode-enterprise-ce#rhodecode
240 240 ## egg:rhodecode-enterprise-ce#pam
241 241 ## egg:rhodecode-enterprise-ce#ldap
242 242 ## egg:rhodecode-enterprise-ce#jasig_cas
243 243 ## egg:rhodecode-enterprise-ce#headers
244 244 ## egg:rhodecode-enterprise-ce#crowd
245 245 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
246 246
247 247 ## alternative return HTTP header for failed authentication. Default HTTP
248 248 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
249 249 ## handling that causing a series of failed authentication calls.
250 250 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
251 251 ## This will be served instead of default 401 on bad authnetication
252 252 auth_ret_code =
253 253
254 254 ## use special detection method when serving auth_ret_code, instead of serving
255 255 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
256 256 ## and then serve auth_ret_code to clients
257 257 auth_ret_code_detection = false
258 258
259 259 ## locking return code. When repository is locked return this HTTP code. 2XX
260 260 ## codes don't break the transactions while 4XX codes do
261 261 lock_ret_code = 423
262 262
263 263 ## allows to change the repository location in settings page
264 264 allow_repo_location_change = true
265 265
266 266 ## allows to setup custom hooks in settings page
267 267 allow_custom_hooks_settings = true
268 268
269 269 ## generated license token, goto license page in RhodeCode settings to obtain
270 270 ## new token
271 271 license_token =
272 272
273 273 ## supervisor connection uri, for managing supervisor and logs.
274 274 supervisor.uri =
275 275 ## supervisord group name/id we only want this RC instance to handle
276 276 supervisor.group_id = dev
277 277
278 278 ## Display extended labs settings
279 279 labs_settings_active = true
280 280
281 281 ####################################
282 282 ### CELERY CONFIG ####
283 283 ####################################
284 284 use_celery = false
285 285 broker.host = localhost
286 286 broker.vhost = rabbitmqhost
287 287 broker.port = 5672
288 288 broker.user = rabbitmq
289 289 broker.password = qweqwe
290 290
291 291 celery.imports = rhodecode.lib.celerylib.tasks
292 292
293 293 celery.result.backend = amqp
294 294 celery.result.dburi = amqp://
295 295 celery.result.serialier = json
296 296
297 297 #celery.send.task.error.emails = true
298 298 #celery.amqp.task.result.expires = 18000
299 299
300 300 celeryd.concurrency = 2
301 301 #celeryd.log.file = celeryd.log
302 302 celeryd.log.level = debug
303 303 celeryd.max.tasks.per.child = 1
304 304
305 305 ## tasks will never be sent to the queue, but executed locally instead.
306 306 celery.always.eager = false
307 307
308 308 ####################################
309 309 ### BEAKER CACHE ####
310 310 ####################################
311 311 # default cache dir for templates. Putting this into a ramdisk
312 312 ## can boost performance, eg. %(here)s/data_ramdisk
313 313 cache_dir = %(here)s/data
314 314
315 315 ## locking and default file storage for Beaker. Putting this into a ramdisk
316 316 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
317 317 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
318 318 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
319 319
320 320 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
321 321
322 322 beaker.cache.super_short_term.type = memory
323 323 beaker.cache.super_short_term.expire = 10
324 324 beaker.cache.super_short_term.key_length = 256
325 325
326 326 beaker.cache.short_term.type = memory
327 327 beaker.cache.short_term.expire = 60
328 328 beaker.cache.short_term.key_length = 256
329 329
330 330 beaker.cache.long_term.type = memory
331 331 beaker.cache.long_term.expire = 36000
332 332 beaker.cache.long_term.key_length = 256
333 333
334 334 beaker.cache.sql_cache_short.type = memory
335 335 beaker.cache.sql_cache_short.expire = 10
336 336 beaker.cache.sql_cache_short.key_length = 256
337 337
338 338 ## default is memory cache, configure only if required
339 339 ## using multi-node or multi-worker setup
340 340 #beaker.cache.auth_plugins.type = ext:database
341 341 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
342 342 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
343 343 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
344 344 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
345 345 #beaker.cache.auth_plugins.sa.pool_size = 10
346 346 #beaker.cache.auth_plugins.sa.max_overflow = 0
347 347
348 348 beaker.cache.repo_cache_long.type = memorylru_base
349 349 beaker.cache.repo_cache_long.max_items = 4096
350 350 beaker.cache.repo_cache_long.expire = 2592000
351 351
352 352 ## default is memorylru_base cache, configure only if required
353 353 ## using multi-node or multi-worker setup
354 354 #beaker.cache.repo_cache_long.type = ext:memcached
355 355 #beaker.cache.repo_cache_long.url = localhost:11211
356 356 #beaker.cache.repo_cache_long.expire = 1209600
357 357 #beaker.cache.repo_cache_long.key_length = 256
358 358
359 359 ####################################
360 360 ### BEAKER SESSION ####
361 361 ####################################
362 362
363 363 ## .session.type is type of storage options for the session, current allowed
364 364 ## types are file, ext:memcached, ext:database, and memory (default).
365 365 beaker.session.type = file
366 366 beaker.session.data_dir = %(here)s/data/sessions/data
367 367
368 368 ## db based session, fast, and allows easy management over logged in users
369 369 #beaker.session.type = ext:database
370 370 #beaker.session.table_name = db_session
371 371 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
372 372 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
373 373 #beaker.session.sa.pool_recycle = 3600
374 374 #beaker.session.sa.echo = false
375 375
376 376 beaker.session.key = rhodecode
377 377 beaker.session.secret = develop-rc-uytcxaz
378 378 beaker.session.lock_dir = %(here)s/data/sessions/lock
379 379
380 380 ## Secure encrypted cookie. Requires AES and AES python libraries
381 381 ## you must disable beaker.session.secret to use this
382 382 #beaker.session.encrypt_key = key_for_encryption
383 383 #beaker.session.validate_key = validation_key
384 384
385 385 ## sets session as invalid(also logging out user) if it haven not been
386 386 ## accessed for given amount of time in seconds
387 387 beaker.session.timeout = 2592000
388 388 beaker.session.httponly = true
389 389 ## Path to use for the cookie. Set to prefix if you use prefix middleware
390 390 #beaker.session.cookie_path = /custom_prefix
391 391
392 392 ## uncomment for https secure cookie
393 393 beaker.session.secure = false
394 394
395 395 ## auto save the session to not to use .save()
396 396 beaker.session.auto = false
397 397
398 398 ## default cookie expiration time in seconds, set to `true` to set expire
399 399 ## at browser close
400 400 #beaker.session.cookie_expires = 3600
401 401
402 402 ###################################
403 403 ## SEARCH INDEXING CONFIGURATION ##
404 404 ###################################
405 405 ## Full text search indexer is available in rhodecode-tools under
406 406 ## `rhodecode-tools index` command
407 407
408 408 ## WHOOSH Backend, doesn't require additional services to run
409 409 ## it works good with few dozen repos
410 410 search.module = rhodecode.lib.index.whoosh
411 411 search.location = %(here)s/data/index
412 412
413 413 ########################################
414 414 ### CHANNELSTREAM CONFIG ####
415 415 ########################################
416 416 ## channelstream enables persistent connections and live notification
417 417 ## in the system. It's also used by the chat system
418 channelstream.enabled = false
418 419
419 channelstream.enabled = false
420 ## location of channelstream server on the backend
420 ## server address for channelstream server on the backend
421 421 channelstream.server = 127.0.0.1:9800
422
422 423 ## location of the channelstream server from outside world
423 ## most likely this would be an http server special backend URL, that handles
424 ## websocket connections see nginx example for config
425 # channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
426 ## proxy path that can be used by http daemons for exposing channelstream
427 # channelstream.proxy_path = /_channelstream
424 ## use ws:// for http or wss:// for https. This address needs to be handled
425 ## by external HTTP server such as Nginx or Apache
426 ## see nginx/apache configuration examples in our docs
427 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
428 428 channelstream.secret = secret
429 429 channelstream.history.location = %(here)s/channelstream_history
430 430
431 ## Internal application path that Javascript uses to connect into.
432 ## If you use proxy-prefix the prefix should be added before /_channelstream
433 channelstream.proxy_path = /_channelstream
434
431 435
432 436 ###################################
433 437 ## APPENLIGHT CONFIG ##
434 438 ###################################
435 439
436 440 ## Appenlight is tailored to work with RhodeCode, see
437 441 ## http://appenlight.com for details how to obtain an account
438 442
439 443 ## appenlight integration enabled
440 444 appenlight = false
441 445
442 446 appenlight.server_url = https://api.appenlight.com
443 447 appenlight.api_key = YOUR_API_KEY
444 448 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
445 449
446 450 # used for JS client
447 451 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
448 452
449 453 ## TWEAK AMOUNT OF INFO SENT HERE
450 454
451 455 ## enables 404 error logging (default False)
452 456 appenlight.report_404 = false
453 457
454 458 ## time in seconds after request is considered being slow (default 1)
455 459 appenlight.slow_request_time = 1
456 460
457 461 ## record slow requests in application
458 462 ## (needs to be enabled for slow datastore recording and time tracking)
459 463 appenlight.slow_requests = true
460 464
461 465 ## enable hooking to application loggers
462 466 appenlight.logging = true
463 467
464 468 ## minimum log level for log capture
465 469 appenlight.logging.level = WARNING
466 470
467 471 ## send logs only from erroneous/slow requests
468 472 ## (saves API quota for intensive logging)
469 473 appenlight.logging_on_error = false
470 474
471 475 ## list of additonal keywords that should be grabbed from environ object
472 476 ## can be string with comma separated list of words in lowercase
473 477 ## (by default client will always send following info:
474 478 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
475 479 ## start with HTTP* this list be extended with additional keywords here
476 480 appenlight.environ_keys_whitelist =
477 481
478 482 ## list of keywords that should be blanked from request object
479 483 ## can be string with comma separated list of words in lowercase
480 484 ## (by default client will always blank keys that contain following words
481 485 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
482 486 ## this list be extended with additional keywords set here
483 487 appenlight.request_keys_blacklist =
484 488
485 489 ## list of namespaces that should be ignores when gathering log entries
486 490 ## can be string with comma separated list of namespaces
487 491 ## (by default the client ignores own entries: appenlight_client.client)
488 492 appenlight.log_namespace_blacklist =
489 493
490 494
491 495 ################################################################################
492 496 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
493 497 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
494 498 ## execute malicious code after an exception is raised. ##
495 499 ################################################################################
496 500 #set debug = false
497 501
498 502
499 503 ##############
500 504 ## STYLING ##
501 505 ##############
502 506 debug_style = true
503 507
504 #########################################################
505 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
506 #########################################################
508 ###########################################
509 ### MAIN RHODECODE DATABASE CONFIG ###
510 ###########################################
507 511 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
508 512 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
509 513 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
510 514 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
511 515
512 516 # see sqlalchemy docs for other advanced settings
513 517
514 518 ## print the sql statements to output
515 519 sqlalchemy.db1.echo = false
516 520 ## recycle the connections after this amount of seconds
517 521 sqlalchemy.db1.pool_recycle = 3600
518 522 sqlalchemy.db1.convert_unicode = true
519 523
520 524 ## the number of connections to keep open inside the connection pool.
521 525 ## 0 indicates no limit
522 526 #sqlalchemy.db1.pool_size = 5
523 527
524 528 ## the number of connections to allow in connection pool "overflow", that is
525 529 ## connections that can be opened above and beyond the pool_size setting,
526 530 ## which defaults to five.
527 531 #sqlalchemy.db1.max_overflow = 10
528 532
529 533
530 534 ##################
531 535 ### VCS CONFIG ###
532 536 ##################
533 537 vcs.server.enable = true
534 538 vcs.server = localhost:9900
535 539
536 540 ## Web server connectivity protocol, responsible for web based VCS operatations
537 541 ## Available protocols are:
538 542 ## `pyro4` - use pyro4 server
539 543 ## `http` - use http-rpc backend (default)
540 544 vcs.server.protocol = http
541 545
542 546 ## Push/Pull operations protocol, available options are:
543 547 ## `pyro4` - use pyro4 server
544 548 ## `http` - use http-rpc backend (default)
545 549 ##
546 550 vcs.scm_app_implementation = http
547 551
548 552 ## Push/Pull operations hooks protocol, available options are:
549 553 ## `pyro4` - use pyro4 server
550 554 ## `http` - use http-rpc backend (default)
551 555 vcs.hooks.protocol = http
552 556
553 557 vcs.server.log_level = debug
554 558 ## Start VCSServer with this instance as a subprocess, usefull for development
555 559 vcs.start_server = true
556 560
557 561 ## List of enabled VCS backends, available options are:
558 562 ## `hg` - mercurial
559 563 ## `git` - git
560 564 ## `svn` - subversion
561 565 vcs.backends = hg, git, svn
562 566
563 567 vcs.connection_timeout = 3600
564 568 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
565 569 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
566 570 #vcs.svn.compatible_version = pre-1.8-compatible
567 571
568 572
569 573 ############################################################
570 574 ### Subversion proxy support (mod_dav_svn) ###
571 575 ### Maps RhodeCode repo groups into SVN paths for Apache ###
572 576 ############################################################
573 577 ## Enable or disable the config file generation.
574 578 svn.proxy.generate_config = false
575 579 ## Generate config file with `SVNListParentPath` set to `On`.
576 580 svn.proxy.list_parent_path = true
577 581 ## Set location and file name of generated config file.
578 582 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
579 583 ## Used as a prefix to the `Location` block in the generated config file.
580 584 ## In most cases it should be set to `/`.
581 585 svn.proxy.location_root = /
582 586 ## Command to reload the mod dav svn configuration on change.
583 587 ## Example: `/etc/init.d/apache2 reload`
584 588 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
585 589 ## If the timeout expires before the reload command finishes, the command will
586 590 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
587 591 #svn.proxy.reload_timeout = 10
588 592
593 ## Dummy marker to add new entries after.
594 ## Add any custom entries below. Please don't remove.
595 custom.conf = 1
596
589 597
590 598 ################################
591 599 ### LOGGING CONFIGURATION ####
592 600 ################################
593 601 [loggers]
594 keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates
602 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
595 603
596 604 [handlers]
597 605 keys = console, console_sql
598 606
599 607 [formatters]
600 608 keys = generic, color_formatter, color_formatter_sql
601 609
602 610 #############
603 611 ## LOGGERS ##
604 612 #############
605 613 [logger_root]
606 614 level = NOTSET
607 615 handlers = console
608 616
609 617 [logger_routes]
610 618 level = DEBUG
611 619 handlers =
612 620 qualname = routes.middleware
613 621 ## "level = DEBUG" logs the route matched and routing variables.
614 622 propagate = 1
615 623
616 624 [logger_beaker]
617 625 level = DEBUG
618 626 handlers =
619 627 qualname = beaker.container
620 628 propagate = 1
621 629
622 [logger_pyro4]
623 level = DEBUG
624 handlers =
625 qualname = Pyro4
626 propagate = 1
627
628 630 [logger_templates]
629 631 level = INFO
630 632 handlers =
631 633 qualname = pylons.templating
632 634 propagate = 1
633 635
634 636 [logger_rhodecode]
635 637 level = DEBUG
636 638 handlers =
637 639 qualname = rhodecode
638 640 propagate = 1
639 641
640 642 [logger_sqlalchemy]
641 643 level = INFO
642 644 handlers = console_sql
643 645 qualname = sqlalchemy.engine
644 646 propagate = 0
645 647
646 648 ##############
647 649 ## HANDLERS ##
648 650 ##############
649 651
650 652 [handler_console]
651 653 class = StreamHandler
652 args = (sys.stderr,)
654 args = (sys.stderr, )
653 655 level = DEBUG
654 656 formatter = color_formatter
655 657
656 658 [handler_console_sql]
657 659 class = StreamHandler
658 args = (sys.stderr,)
660 args = (sys.stderr, )
659 661 level = DEBUG
660 662 formatter = color_formatter_sql
661 663
662 664 ################
663 665 ## FORMATTERS ##
664 666 ################
665 667
666 668 [formatter_generic]
667 669 class = rhodecode.lib.logging_formatter.Pyro4AwareFormatter
668 670 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
669 671 datefmt = %Y-%m-%d %H:%M:%S
670 672
671 673 [formatter_color_formatter]
672 674 class = rhodecode.lib.logging_formatter.ColorFormatter
673 675 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
674 676 datefmt = %Y-%m-%d %H:%M:%S
675 677
676 678 [formatter_color_formatter_sql]
677 679 class = rhodecode.lib.logging_formatter.ColorFormatterSql
678 680 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
679 681 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,96 +1,90 b''
1 """gunicorn config hooks"""
1 """
2 gunicorn config extension and hooks. Sets additional configuration that is
3 available post the .ini config.
4
5 - workers = ${cpu_number}
6 - threads = 1
7 - proc_name = ${gunicorn_proc_name}
8 - worker_class = sync
9 - worker_connections = 10
10 - max_requests = 1000
11 - max_requests_jitter = 30
12 - timeout = 21600
13
14 """
2 15
3 16 import multiprocessing
4 17 import sys
5 18 import threading
6 19 import traceback
7 20
8 21
9 # GLOBAL #
22 # GLOBAL
10 23 errorlog = '-'
11 24 accesslog = '-'
12 25 loglevel = 'debug'
13 26
14 # SECURITY #
27 # SECURITY
15 28 limit_request_line = 4094
16 29 limit_request_fields = 100
17 30 limit_request_field_size = 8190
18 31
19 # SERVER MECHANICS #
20 # None == system temp dir #
32 # SERVER MECHANICS
33 # None == system temp dir
21 34 worker_tmp_dir = None
22 35 tmp_upload_dir = None
23 #proc_name =
24
25 # self adjust workers based on CPU #
26 #workers = multiprocessing.cpu_count() * 2 + 1
27
28 access_log_format = '[%(p)s] %(h)15s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" request_time:%(L)s'
29
30 # For the gevent worker classes #
31 # this limits the maximum number of simultaneous clients that #
32 # a single process can handle. #
33 #worker_connections = 10
34 36
35 # Max requests to handle by each worker before restarting it, #
36 # could prevent memory leaks #
37 #max_requests = 1000
38 #max_requests_jitter = 30
39
37 # Custom log format
38 access_log_format = (
39 '%(t)s GNCRN %(p)-8s %(h)-15s rqt:%(L)s %(s)s %(b)s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
40 40
41 # If a worker does not notify the master process in this #
42 # number of seconds it is killed and a new worker is spawned #
43 # to replace it. #
44 #timeout = 3600
45
46 access_log_format = (
47 '[%(p)-10s] %(h)s time:%(L)s %(l)s %(u)s '
48 '%(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"')
41 # self adjust workers based on CPU count
42 # workers = multiprocessing.cpu_count() * 2 + 1
49 43
50 44
51 45 def post_fork(server, worker):
52 server.log.info("[<%s>] worker spawned", worker.pid)
46 server.log.info("[<%-10s>] WORKER spawned", worker.pid)
53 47
54 48
55 49 def pre_fork(server, worker):
56 50 pass
57 51
58 52
59 53 def pre_exec(server):
60 54 server.log.info("Forked child, re-executing.")
61 55
62 56
63 57 def when_ready(server):
64 58 server.log.info("Server is ready. Spawning workers")
65 59
66 60
67 61 def worker_int(worker):
68 62 worker.log.info("[<%-10s>] worker received INT or QUIT signal", worker.pid)
69 63
70 # get traceback info
64 # get traceback info, on worker crash
71 65 id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
72 66 code = []
73 67 for thread_id, stack in sys._current_frames().items():
74 68 code.append(
75 69 "\n# Thread: %s(%d)" % (id2name.get(thread_id, ""), thread_id))
76 70 for fname, lineno, name, line in traceback.extract_stack(stack):
77 71 code.append('File: "%s", line %d, in %s' % (fname, lineno, name))
78 72 if line:
79 73 code.append(" %s" % (line.strip()))
80 74 worker.log.debug("\n".join(code))
81 75
82 76
83 77 def worker_abort(worker):
84 78 worker.log.info("[<%-10s>] worker received SIGABRT signal", worker.pid)
85 79
86 80
87 81 def pre_request(worker, req):
88 82 return
89 83 worker.log.debug("[<%-10s>] PRE WORKER: %s %s",
90 84 worker.pid, req.method, req.path)
91 85
92 86
93 87 def post_request(worker, req, environ, resp):
94 88 return
95 89 worker.log.debug("[<%-10s>] POST WORKER: %s %s resp: %s", worker.pid,
96 90 req.method, req.path, resp.status_code) No newline at end of file
@@ -1,648 +1,650 b''
1 1
2 2
3 3 ################################################################################
4 4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10
11 11 ################################################################################
12 12 ## EMAIL CONFIGURATION ##
13 13 ## Uncomment and replace with the email address which should receive ##
14 14 ## any error reports after an application crash ##
15 15 ## Additionally these settings will be used by the RhodeCode mailing system ##
16 16 ################################################################################
17 17
18 18 ## prefix all emails subjects with given prefix, helps filtering out emails
19 19 #email_prefix = [RhodeCode]
20 20
21 21 ## email FROM address all mails will be sent
22 22 #app_email_from = rhodecode-noreply@localhost
23 23
24 24 ## Uncomment and replace with the address which should receive any error report
25 25 ## note: using appenlight for error handling doesn't need this to be uncommented
26 26 #email_to = admin@localhost
27 27
28 28 ## in case of Application errors, sent an error email form
29 29 #error_email_from = rhodecode_error@localhost
30 30
31 31 ## additional error message to be send in case of server crash
32 32 #error_message =
33 33
34 34
35 35 #smtp_server = mail.server.com
36 36 #smtp_username =
37 37 #smtp_password =
38 38 #smtp_port =
39 39 #smtp_use_tls = false
40 40 #smtp_use_ssl = true
41 41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
42 42 #smtp_auth =
43 43
44 44 [server:main]
45 45 ## COMMON ##
46 46 host = 127.0.0.1
47 47 port = 5000
48 48
49 49 ##################################
50 50 ## WAITRESS WSGI SERVER ##
51 51 ## Recommended for Development ##
52 52 ##################################
53 53
54 54 #use = egg:waitress#main
55 55 ## number of worker threads
56 56 #threads = 5
57 57 ## MAX BODY SIZE 100GB
58 58 #max_request_body_size = 107374182400
59 59 ## Use poll instead of select, fixes file descriptors limits problems.
60 60 ## May not work on old windows systems.
61 61 #asyncore_use_poll = true
62 62
63 63
64 64 ##########################
65 65 ## GUNICORN WSGI SERVER ##
66 66 ##########################
67 67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68 68
69 69 use = egg:gunicorn#main
70 70 ## Sets the number of process workers. You must set `instance_id = *`
71 71 ## when this option is set to more than one worker, recommended
72 72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
73 73 ## The `instance_id = *` must be set in the [app:main] section below
74 74 workers = 2
75 75 ## number of threads for each of the worker, must be set to 1 for gevent
76 76 ## generally recommened to be at 1
77 77 #threads = 1
78 78 ## process name
79 79 proc_name = rhodecode
80 80 ## type of worker class, one of sync, gevent
81 81 ## recommended for bigger setup is using of of other than sync one
82 82 worker_class = sync
83 83 ## The maximum number of simultaneous clients. Valid only for Gevent
84 84 #worker_connections = 10
85 85 ## max number of requests that worker will handle before being gracefully
86 86 ## restarted, could prevent memory leaks
87 87 max_requests = 1000
88 88 max_requests_jitter = 30
89 89 ## amount of time a worker can spend with handling a request before it
90 90 ## gets killed and restarted. Set to 6hrs
91 91 timeout = 21600
92 92
93 93
94 94 ## prefix middleware for RhodeCode.
95 95 ## recommended when using proxy setup.
96 96 ## allows to set RhodeCode under a prefix in server.
97 97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
98 98 ## And set your prefix like: `prefix = /custom_prefix`
99 99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
100 100 ## to make your cookies only work on prefix url
101 101 [filter:proxy-prefix]
102 102 use = egg:PasteDeploy#prefix
103 103 prefix = /
104 104
105 105 [app:main]
106 106 use = egg:rhodecode-enterprise-ce
107 107
108 108 ## enable proxy prefix middleware, defined above
109 109 #filter-with = proxy-prefix
110 110
111 111 ## encryption key used to encrypt social plugin tokens,
112 112 ## remote_urls with credentials etc, if not set it defaults to
113 113 ## `beaker.session.secret`
114 114 #rhodecode.encrypted_values.secret =
115 115
116 116 ## decryption strict mode (enabled by default). It controls if decryption raises
117 117 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
118 118 #rhodecode.encrypted_values.strict = false
119 119
120 120 ## return gzipped responses from Rhodecode (static files/application)
121 121 gzip_responses = false
122 122
123 123 ## autogenerate javascript routes file on startup
124 124 generate_js_files = false
125 125
126 126 ## Optional Languages
127 127 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
128 128 lang = en
129 129
130 130 ## perform a full repository scan on each server start, this should be
131 131 ## set to false after first startup, to allow faster server restarts.
132 132 startup.import_repos = false
133 133
134 134 ## Uncomment and set this path to use archive download cache.
135 135 ## Once enabled, generated archives will be cached at this location
136 136 ## and served from the cache during subsequent requests for the same archive of
137 137 ## the repository.
138 138 #archive_cache_dir = /tmp/tarballcache
139 139
140 140 ## change this to unique ID for security
141 141 app_instance_uuid = rc-production
142 142
143 143 ## cut off limit for large diffs (size in bytes)
144 144 cut_off_limit_diff = 1024000
145 145 cut_off_limit_file = 256000
146 146
147 147 ## use cache version of scm repo everywhere
148 148 vcs_full_cache = true
149 149
150 150 ## force https in RhodeCode, fixes https redirects, assumes it's always https
151 151 ## Normally this is controlled by proper http flags sent from http server
152 152 force_https = false
153 153
154 154 ## use Strict-Transport-Security headers
155 155 use_htsts = false
156 156
157 157 ## number of commits stats will parse on each iteration
158 158 commit_parse_limit = 25
159 159
160 160 ## git rev filter option, --all is the default filter, if you need to
161 161 ## hide all refs in changelog switch this to --branches --tags
162 162 git_rev_filter = --branches --tags
163 163
164 164 # Set to true if your repos are exposed using the dumb protocol
165 165 git_update_server_info = false
166 166
167 167 ## RSS/ATOM feed options
168 168 rss_cut_off_limit = 256000
169 169 rss_items_per_page = 10
170 170 rss_include_diff = false
171 171
172 172 ## gist URL alias, used to create nicer urls for gist. This should be an
173 173 ## url that does rewrites to _admin/gists/{gistid}.
174 174 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
175 175 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
176 176 gist_alias_url =
177 177
178 178 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
179 179 ## used for access.
180 180 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
181 181 ## came from the the logged in user who own this authentication token.
182 182 ##
183 183 ## Syntax is ControllerClass:function_pattern.
184 184 ## To enable access to raw_files put `FilesController:raw`.
185 185 ## To enable access to patches add `ChangesetController:changeset_patch`.
186 186 ## The list should be "," separated and on a single line.
187 187 ##
188 188 ## Recommended controllers to enable:
189 189 # ChangesetController:changeset_patch,
190 190 # ChangesetController:changeset_raw,
191 191 # FilesController:raw,
192 192 # FilesController:archivefile,
193 193 # GistsController:*,
194 194 api_access_controllers_whitelist =
195 195
196 196 ## default encoding used to convert from and to unicode
197 197 ## can be also a comma separated list of encoding in case of mixed encodings
198 198 default_encoding = UTF-8
199 199
200 200 ## instance-id prefix
201 201 ## a prefix key for this instance used for cache invalidation when running
202 202 ## multiple instances of rhodecode, make sure it's globally unique for
203 203 ## all running rhodecode instances. Leave empty if you don't use it
204 204 instance_id =
205 205
206 206 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
207 207 ## of an authentication plugin also if it is disabled by it's settings.
208 208 ## This could be useful if you are unable to log in to the system due to broken
209 209 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
210 210 ## module to log in again and fix the settings.
211 211 ##
212 212 ## Available builtin plugin IDs (hash is part of the ID):
213 213 ## egg:rhodecode-enterprise-ce#rhodecode
214 214 ## egg:rhodecode-enterprise-ce#pam
215 215 ## egg:rhodecode-enterprise-ce#ldap
216 216 ## egg:rhodecode-enterprise-ce#jasig_cas
217 217 ## egg:rhodecode-enterprise-ce#headers
218 218 ## egg:rhodecode-enterprise-ce#crowd
219 219 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
220 220
221 221 ## alternative return HTTP header for failed authentication. Default HTTP
222 222 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
223 223 ## handling that causing a series of failed authentication calls.
224 224 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
225 225 ## This will be served instead of default 401 on bad authnetication
226 226 auth_ret_code =
227 227
228 228 ## use special detection method when serving auth_ret_code, instead of serving
229 229 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
230 230 ## and then serve auth_ret_code to clients
231 231 auth_ret_code_detection = false
232 232
233 233 ## locking return code. When repository is locked return this HTTP code. 2XX
234 234 ## codes don't break the transactions while 4XX codes do
235 235 lock_ret_code = 423
236 236
237 237 ## allows to change the repository location in settings page
238 238 allow_repo_location_change = true
239 239
240 240 ## allows to setup custom hooks in settings page
241 241 allow_custom_hooks_settings = true
242 242
243 243 ## generated license token, goto license page in RhodeCode settings to obtain
244 244 ## new token
245 245 license_token =
246 246
247 247 ## supervisor connection uri, for managing supervisor and logs.
248 248 supervisor.uri =
249 249 ## supervisord group name/id we only want this RC instance to handle
250 250 supervisor.group_id = prod
251 251
252 252 ## Display extended labs settings
253 253 labs_settings_active = true
254 254
255 255 ####################################
256 256 ### CELERY CONFIG ####
257 257 ####################################
258 258 use_celery = false
259 259 broker.host = localhost
260 260 broker.vhost = rabbitmqhost
261 261 broker.port = 5672
262 262 broker.user = rabbitmq
263 263 broker.password = qweqwe
264 264
265 265 celery.imports = rhodecode.lib.celerylib.tasks
266 266
267 267 celery.result.backend = amqp
268 268 celery.result.dburi = amqp://
269 269 celery.result.serialier = json
270 270
271 271 #celery.send.task.error.emails = true
272 272 #celery.amqp.task.result.expires = 18000
273 273
274 274 celeryd.concurrency = 2
275 275 #celeryd.log.file = celeryd.log
276 276 celeryd.log.level = debug
277 277 celeryd.max.tasks.per.child = 1
278 278
279 279 ## tasks will never be sent to the queue, but executed locally instead.
280 280 celery.always.eager = false
281 281
282 282 ####################################
283 283 ### BEAKER CACHE ####
284 284 ####################################
285 285 # default cache dir for templates. Putting this into a ramdisk
286 286 ## can boost performance, eg. %(here)s/data_ramdisk
287 287 cache_dir = %(here)s/data
288 288
289 289 ## locking and default file storage for Beaker. Putting this into a ramdisk
290 290 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
291 291 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
292 292 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
293 293
294 294 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
295 295
296 296 beaker.cache.super_short_term.type = memory
297 297 beaker.cache.super_short_term.expire = 10
298 298 beaker.cache.super_short_term.key_length = 256
299 299
300 300 beaker.cache.short_term.type = memory
301 301 beaker.cache.short_term.expire = 60
302 302 beaker.cache.short_term.key_length = 256
303 303
304 304 beaker.cache.long_term.type = memory
305 305 beaker.cache.long_term.expire = 36000
306 306 beaker.cache.long_term.key_length = 256
307 307
308 308 beaker.cache.sql_cache_short.type = memory
309 309 beaker.cache.sql_cache_short.expire = 10
310 310 beaker.cache.sql_cache_short.key_length = 256
311 311
312 312 ## default is memory cache, configure only if required
313 313 ## using multi-node or multi-worker setup
314 314 #beaker.cache.auth_plugins.type = ext:database
315 315 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
316 316 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
317 317 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
318 318 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
319 319 #beaker.cache.auth_plugins.sa.pool_size = 10
320 320 #beaker.cache.auth_plugins.sa.max_overflow = 0
321 321
322 322 beaker.cache.repo_cache_long.type = memorylru_base
323 323 beaker.cache.repo_cache_long.max_items = 4096
324 324 beaker.cache.repo_cache_long.expire = 2592000
325 325
326 326 ## default is memorylru_base cache, configure only if required
327 327 ## using multi-node or multi-worker setup
328 328 #beaker.cache.repo_cache_long.type = ext:memcached
329 329 #beaker.cache.repo_cache_long.url = localhost:11211
330 330 #beaker.cache.repo_cache_long.expire = 1209600
331 331 #beaker.cache.repo_cache_long.key_length = 256
332 332
333 333 ####################################
334 334 ### BEAKER SESSION ####
335 335 ####################################
336 336
337 337 ## .session.type is type of storage options for the session, current allowed
338 338 ## types are file, ext:memcached, ext:database, and memory (default).
339 339 beaker.session.type = file
340 340 beaker.session.data_dir = %(here)s/data/sessions/data
341 341
342 342 ## db based session, fast, and allows easy management over logged in users
343 343 #beaker.session.type = ext:database
344 344 #beaker.session.table_name = db_session
345 345 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
346 346 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
347 347 #beaker.session.sa.pool_recycle = 3600
348 348 #beaker.session.sa.echo = false
349 349
350 350 beaker.session.key = rhodecode
351 351 beaker.session.secret = production-rc-uytcxaz
352 352 beaker.session.lock_dir = %(here)s/data/sessions/lock
353 353
354 354 ## Secure encrypted cookie. Requires AES and AES python libraries
355 355 ## you must disable beaker.session.secret to use this
356 356 #beaker.session.encrypt_key = key_for_encryption
357 357 #beaker.session.validate_key = validation_key
358 358
359 359 ## sets session as invalid(also logging out user) if it haven not been
360 360 ## accessed for given amount of time in seconds
361 361 beaker.session.timeout = 2592000
362 362 beaker.session.httponly = true
363 363 ## Path to use for the cookie. Set to prefix if you use prefix middleware
364 364 #beaker.session.cookie_path = /custom_prefix
365 365
366 366 ## uncomment for https secure cookie
367 367 beaker.session.secure = false
368 368
369 369 ## auto save the session to not to use .save()
370 370 beaker.session.auto = false
371 371
372 372 ## default cookie expiration time in seconds, set to `true` to set expire
373 373 ## at browser close
374 374 #beaker.session.cookie_expires = 3600
375 375
376 376 ###################################
377 377 ## SEARCH INDEXING CONFIGURATION ##
378 378 ###################################
379 379 ## Full text search indexer is available in rhodecode-tools under
380 380 ## `rhodecode-tools index` command
381 381
382 382 ## WHOOSH Backend, doesn't require additional services to run
383 383 ## it works good with few dozen repos
384 384 search.module = rhodecode.lib.index.whoosh
385 385 search.location = %(here)s/data/index
386 386
387 387 ########################################
388 388 ### CHANNELSTREAM CONFIG ####
389 389 ########################################
390 390 ## channelstream enables persistent connections and live notification
391 391 ## in the system. It's also used by the chat system
392 channelstream.enabled = false
392 393
393 channelstream.enabled = false
394 ## location of channelstream server on the backend
394 ## server address for channelstream server on the backend
395 395 channelstream.server = 127.0.0.1:9800
396
396 397 ## location of the channelstream server from outside world
397 ## most likely this would be an http server special backend URL, that handles
398 ## websocket connections see nginx example for config
399 # channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
400 ## proxy path that can be used by http daemons for exposing channelstream
401 # channelstream.proxy_path = /_channelstream
398 ## use ws:// for http or wss:// for https. This address needs to be handled
399 ## by external HTTP server such as Nginx or Apache
400 ## see nginx/apache configuration examples in our docs
401 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
402 402 channelstream.secret = secret
403 403 channelstream.history.location = %(here)s/channelstream_history
404 404
405 ## Internal application path that Javascript uses to connect into.
406 ## If you use proxy-prefix the prefix should be added before /_channelstream
407 channelstream.proxy_path = /_channelstream
408
405 409
406 410 ###################################
407 411 ## APPENLIGHT CONFIG ##
408 412 ###################################
409 413
410 414 ## Appenlight is tailored to work with RhodeCode, see
411 415 ## http://appenlight.com for details how to obtain an account
412 416
413 417 ## appenlight integration enabled
414 418 appenlight = false
415 419
416 420 appenlight.server_url = https://api.appenlight.com
417 421 appenlight.api_key = YOUR_API_KEY
418 422 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
419 423
420 424 # used for JS client
421 425 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
422 426
423 427 ## TWEAK AMOUNT OF INFO SENT HERE
424 428
425 429 ## enables 404 error logging (default False)
426 430 appenlight.report_404 = false
427 431
428 432 ## time in seconds after request is considered being slow (default 1)
429 433 appenlight.slow_request_time = 1
430 434
431 435 ## record slow requests in application
432 436 ## (needs to be enabled for slow datastore recording and time tracking)
433 437 appenlight.slow_requests = true
434 438
435 439 ## enable hooking to application loggers
436 440 appenlight.logging = true
437 441
438 442 ## minimum log level for log capture
439 443 appenlight.logging.level = WARNING
440 444
441 445 ## send logs only from erroneous/slow requests
442 446 ## (saves API quota for intensive logging)
443 447 appenlight.logging_on_error = false
444 448
445 449 ## list of additonal keywords that should be grabbed from environ object
446 450 ## can be string with comma separated list of words in lowercase
447 451 ## (by default client will always send following info:
448 452 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
449 453 ## start with HTTP* this list be extended with additional keywords here
450 454 appenlight.environ_keys_whitelist =
451 455
452 456 ## list of keywords that should be blanked from request object
453 457 ## can be string with comma separated list of words in lowercase
454 458 ## (by default client will always blank keys that contain following words
455 459 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
456 460 ## this list be extended with additional keywords set here
457 461 appenlight.request_keys_blacklist =
458 462
459 463 ## list of namespaces that should be ignores when gathering log entries
460 464 ## can be string with comma separated list of namespaces
461 465 ## (by default the client ignores own entries: appenlight_client.client)
462 466 appenlight.log_namespace_blacklist =
463 467
464 468
465 469 ################################################################################
466 470 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
467 471 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
468 472 ## execute malicious code after an exception is raised. ##
469 473 ################################################################################
470 474 set debug = false
471 475
472 476
473 #########################################################
474 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
475 #########################################################
477 ###########################################
478 ### MAIN RHODECODE DATABASE CONFIG ###
479 ###########################################
476 480 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
477 481 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
478 482 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
479 483 sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
480 484
481 485 # see sqlalchemy docs for other advanced settings
482 486
483 487 ## print the sql statements to output
484 488 sqlalchemy.db1.echo = false
485 489 ## recycle the connections after this amount of seconds
486 490 sqlalchemy.db1.pool_recycle = 3600
487 491 sqlalchemy.db1.convert_unicode = true
488 492
489 493 ## the number of connections to keep open inside the connection pool.
490 494 ## 0 indicates no limit
491 495 #sqlalchemy.db1.pool_size = 5
492 496
493 497 ## the number of connections to allow in connection pool "overflow", that is
494 498 ## connections that can be opened above and beyond the pool_size setting,
495 499 ## which defaults to five.
496 500 #sqlalchemy.db1.max_overflow = 10
497 501
498 502
499 503 ##################
500 504 ### VCS CONFIG ###
501 505 ##################
502 506 vcs.server.enable = true
503 507 vcs.server = localhost:9900
504 508
505 509 ## Web server connectivity protocol, responsible for web based VCS operatations
506 510 ## Available protocols are:
507 511 ## `pyro4` - use pyro4 server
508 512 ## `http` - use http-rpc backend (default)
509 513 vcs.server.protocol = http
510 514
511 515 ## Push/Pull operations protocol, available options are:
512 516 ## `pyro4` - use pyro4 server
513 517 ## `http` - use http-rpc backend (default)
514 518 ##
515 519 vcs.scm_app_implementation = http
516 520
517 521 ## Push/Pull operations hooks protocol, available options are:
518 522 ## `pyro4` - use pyro4 server
519 523 ## `http` - use http-rpc backend (default)
520 524 vcs.hooks.protocol = http
521 525
522 526 vcs.server.log_level = info
523 527 ## Start VCSServer with this instance as a subprocess, usefull for development
524 528 vcs.start_server = false
525 529
526 530 ## List of enabled VCS backends, available options are:
527 531 ## `hg` - mercurial
528 532 ## `git` - git
529 533 ## `svn` - subversion
530 534 vcs.backends = hg, git, svn
531 535
532 536 vcs.connection_timeout = 3600
533 537 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
534 538 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
535 539 #vcs.svn.compatible_version = pre-1.8-compatible
536 540
537 541
538 542 ############################################################
539 543 ### Subversion proxy support (mod_dav_svn) ###
540 544 ### Maps RhodeCode repo groups into SVN paths for Apache ###
541 545 ############################################################
542 546 ## Enable or disable the config file generation.
543 547 svn.proxy.generate_config = false
544 548 ## Generate config file with `SVNListParentPath` set to `On`.
545 549 svn.proxy.list_parent_path = true
546 550 ## Set location and file name of generated config file.
547 551 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
548 552 ## Used as a prefix to the `Location` block in the generated config file.
549 553 ## In most cases it should be set to `/`.
550 554 svn.proxy.location_root = /
551 555 ## Command to reload the mod dav svn configuration on change.
552 556 ## Example: `/etc/init.d/apache2 reload`
553 557 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
554 558 ## If the timeout expires before the reload command finishes, the command will
555 559 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
556 560 #svn.proxy.reload_timeout = 10
557 561
562 ## Dummy marker to add new entries after.
563 ## Add any custom entries below. Please don't remove.
564 custom.conf = 1
565
558 566
559 567 ################################
560 568 ### LOGGING CONFIGURATION ####
561 569 ################################
562 570 [loggers]
563 keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates
571 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
564 572
565 573 [handlers]
566 574 keys = console, console_sql
567 575
568 576 [formatters]
569 577 keys = generic, color_formatter, color_formatter_sql
570 578
571 579 #############
572 580 ## LOGGERS ##
573 581 #############
574 582 [logger_root]
575 583 level = NOTSET
576 584 handlers = console
577 585
578 586 [logger_routes]
579 587 level = DEBUG
580 588 handlers =
581 589 qualname = routes.middleware
582 590 ## "level = DEBUG" logs the route matched and routing variables.
583 591 propagate = 1
584 592
585 593 [logger_beaker]
586 594 level = DEBUG
587 595 handlers =
588 596 qualname = beaker.container
589 597 propagate = 1
590 598
591 [logger_pyro4]
592 level = DEBUG
593 handlers =
594 qualname = Pyro4
595 propagate = 1
596
597 599 [logger_templates]
598 600 level = INFO
599 601 handlers =
600 602 qualname = pylons.templating
601 603 propagate = 1
602 604
603 605 [logger_rhodecode]
604 606 level = DEBUG
605 607 handlers =
606 608 qualname = rhodecode
607 609 propagate = 1
608 610
609 611 [logger_sqlalchemy]
610 612 level = INFO
611 613 handlers = console_sql
612 614 qualname = sqlalchemy.engine
613 615 propagate = 0
614 616
615 617 ##############
616 618 ## HANDLERS ##
617 619 ##############
618 620
619 621 [handler_console]
620 622 class = StreamHandler
621 args = (sys.stderr,)
623 args = (sys.stderr, )
622 624 level = INFO
623 625 formatter = generic
624 626
625 627 [handler_console_sql]
626 628 class = StreamHandler
627 args = (sys.stderr,)
629 args = (sys.stderr, )
628 630 level = WARN
629 631 formatter = generic
630 632
631 633 ################
632 634 ## FORMATTERS ##
633 635 ################
634 636
635 637 [formatter_generic]
636 638 class = rhodecode.lib.logging_formatter.Pyro4AwareFormatter
637 639 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
638 640 datefmt = %Y-%m-%d %H:%M:%S
639 641
640 642 [formatter_color_formatter]
641 643 class = rhodecode.lib.logging_formatter.ColorFormatter
642 644 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
643 645 datefmt = %Y-%m-%d %H:%M:%S
644 646
645 647 [formatter_color_formatter_sql]
646 648 class = rhodecode.lib.logging_formatter.ColorFormatterSql
647 649 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
648 650 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,238 +1,240 b''
1 1 # Nix environment for the community edition
2 2 #
3 3 # This shall be as lean as possible, just producing the Enterprise
4 4 # derivation. For advanced tweaks to pimp up the development environment we use
5 5 # "shell.nix" so that it does not have to clutter this file.
6 6
7 7 args@
8 8 { pythonPackages ? "python27Packages"
9 9 , pythonExternalOverrides ? self: super: {}
10 10 , doCheck ? true
11 11 , ...
12 12 }:
13 13
14 14 let
15 15
16 16 # Use nixpkgs from args or import them. We use this indirect approach
17 17 # through args to be able to use the name `pkgs` for our customized packages.
18 18 # Otherwise we will end up with an infinite recursion.
19 19 nixpkgs = args.pkgs or (import <nixpkgs> { });
20 20
21 21 # johbo: Interim bridge which allows us to build with the upcoming
22 22 # nixos.16.09 branch (unstable at the moment of writing this note) and the
23 23 # current stable nixos-16.03.
24 24 backwardsCompatibleFetchgit = { ... }@args:
25 25 let
26 26 origSources = nixpkgs.fetchgit args;
27 27 in
28 28 nixpkgs.lib.overrideDerivation origSources (oldAttrs: {
29 29 NIX_PREFETCH_GIT_CHECKOUT_HOOK = ''
30 30 find $out -name '.git*' -print0 | xargs -0 rm -rf
31 31 '';
32 32 });
33 33
34 34 # Create a customized version of nixpkgs which should be used throughout the
35 35 # rest of this file.
36 36 pkgs = nixpkgs.overridePackages (self: super: {
37 37 fetchgit = backwardsCompatibleFetchgit;
38 38 });
39 39
40 40 # Evaluates to the last segment of a file system path.
41 41 basename = path: with pkgs.lib; last (splitString "/" path);
42 42
43 43 # source code filter used as arugment to builtins.filterSource.
44 44 src-filter = path: type: with pkgs.lib;
45 45 let
46 46 ext = last (splitString "." path);
47 47 in
48 48 !builtins.elem (basename path) [
49 49 ".git" ".hg" "__pycache__" ".eggs"
50 50 "bower_components" "node_modules"
51 51 "build" "data" "result" "tmp"] &&
52 52 !builtins.elem ext ["egg-info" "pyc"] &&
53 53 # TODO: johbo: This check is wrong, since "path" contains an absolute path,
54 54 # it would still be good to restore it since we want to ignore "result-*".
55 55 !hasPrefix "result" path;
56 56
57 57 basePythonPackages = with builtins; if isAttrs pythonPackages
58 58 then pythonPackages
59 59 else getAttr pythonPackages pkgs;
60 60
61 61 buildBowerComponents =
62 62 pkgs.buildBowerComponents or
63 63 (import ./pkgs/backport-16.03-build-bower-components.nix { inherit pkgs; });
64 64
65 65 sources = pkgs.config.rc.sources or {};
66 66 version = builtins.readFile ./rhodecode/VERSION;
67 67 rhodecode-enterprise-ce-src = builtins.filterSource src-filter ./.;
68 68
69 69 nodeEnv = import ./pkgs/node-default.nix {
70 70 inherit pkgs;
71 71 };
72 72 nodeDependencies = nodeEnv.shell.nodeDependencies;
73 73
74 74 bowerComponents = buildBowerComponents {
75 75 name = "enterprise-ce-${version}";
76 76 generated = ./pkgs/bower-packages.nix;
77 77 src = rhodecode-enterprise-ce-src;
78 78 };
79 79
80 80 pythonGeneratedPackages = self: basePythonPackages.override (a: {
81 81 inherit self;
82 82 })
83 83 // (scopedImport {
84 84 self = self;
85 85 super = basePythonPackages;
86 86 inherit pkgs;
87 87 inherit (pkgs) fetchurl fetchgit;
88 88 } ./pkgs/python-packages.nix);
89 89
90 90 pythonOverrides = import ./pkgs/python-packages-overrides.nix {
91 91 inherit
92 92 basePythonPackages
93 93 pkgs;
94 94 };
95 95
96 96 pythonLocalOverrides = self: super: {
97 97 rhodecode-enterprise-ce =
98 98 let
99 99 linkNodeAndBowerPackages = ''
100 100 echo "Export RhodeCode CE path"
101 101 export RHODECODE_CE_PATH=${rhodecode-enterprise-ce-src}
102 102 echo "Link node packages"
103 103 rm -fr node_modules
104 104 mkdir node_modules
105 105 # johbo: Linking individual packages allows us to run "npm install"
106 106 # inside of a shell to try things out. Re-entering the shell will
107 107 # restore a clean environment.
108 108 ln -s ${nodeDependencies}/lib/node_modules/* node_modules/
109 109
110 110 echo "DONE: Link node packages"
111 111
112 112 echo "Link bower packages"
113 113 rm -fr bower_components
114 114 mkdir bower_components
115 115
116 116 ln -s ${bowerComponents}/bower_components/* bower_components/
117 117 echo "DONE: Link bower packages"
118 118 '';
119 119 in super.rhodecode-enterprise-ce.override (attrs: {
120 120
121 121 inherit
122 122 doCheck
123 123 version;
124 124 name = "rhodecode-enterprise-ce-${version}";
125 125 releaseName = "RhodeCodeEnterpriseCE-${version}";
126 126 src = rhodecode-enterprise-ce-src;
127 127
128 128 buildInputs =
129 129 attrs.buildInputs ++
130 130 (with self; [
131 131 pkgs.nodePackages.bower
132 132 pkgs.nodePackages.grunt-cli
133 133 pkgs.subversion
134 134 pytest-catchlog
135 135 rhodecode-testdata
136 136 ]);
137 137
138 #TODO: either move this into overrides, OR use the new machanics from
139 # pip2nix and requiremtn.txt file
138 140 propagatedBuildInputs = attrs.propagatedBuildInputs ++ (with self; [
139 141 rhodecode-tools
140 142 ]);
141 143
142 144 # TODO: johbo: Make a nicer way to expose the parts. Maybe
143 145 # pkgs/default.nix?
144 146 passthru = {
145 147 inherit
146 148 bowerComponents
147 149 linkNodeAndBowerPackages
148 150 myPythonPackagesUnfix
149 151 pythonLocalOverrides;
150 152 pythonPackages = self;
151 153 };
152 154
153 155 LC_ALL = "en_US.UTF-8";
154 156 LOCALE_ARCHIVE =
155 157 if pkgs.stdenv ? glibc
156 158 then "${pkgs.glibcLocales}/lib/locale/locale-archive"
157 159 else "";
158 160
159 161 preCheck = ''
160 162 export PATH="$out/bin:$PATH"
161 163 '';
162 164
163 165 postCheck = ''
164 166 rm -rf $out/lib/${self.python.libPrefix}/site-packages/pytest_pylons
165 167 rm -rf $out/lib/${self.python.libPrefix}/site-packages/rhodecode/tests
166 168 '';
167 169
168 170 preBuild = linkNodeAndBowerPackages + ''
169 171 grunt
170 172 rm -fr node_modules
171 173 '';
172 174
173 175 postInstall = ''
174 176 # python based programs need to be wrapped
175 177 ln -s ${self.supervisor}/bin/supervisor* $out/bin/
176 178 ln -s ${self.gunicorn}/bin/gunicorn $out/bin/
177 179 ln -s ${self.PasteScript}/bin/paster $out/bin/
178 180 ln -s ${self.channelstream}/bin/channelstream $out/bin/
179 181 ln -s ${self.pyramid}/bin/* $out/bin/ #*/
180 182
181 183 # rhodecode-tools
182 184 # TODO: johbo: re-think this. Do the tools import anything from enterprise?
183 185 ln -s ${self.rhodecode-tools}/bin/rhodecode-* $out/bin/
184 186
185 187 # note that condition should be restricted when adding further tools
186 188 for file in $out/bin/*; do #*/
187 189 wrapProgram $file \
188 190 --prefix PYTHONPATH : $PYTHONPATH \
189 191 --prefix PATH : $PATH \
190 192 --set PYTHONHASHSEED random
191 193 done
192 194
193 195 mkdir $out/etc
194 196 cp configs/production.ini $out/etc
195 197
196 198 echo "Writing meta information for rccontrol to nix-support/rccontrol"
197 199 mkdir -p $out/nix-support/rccontrol
198 200 cp -v rhodecode/VERSION $out/nix-support/rccontrol/version
199 201 echo "DONE: Meta information for rccontrol written"
200 202
201 203 # TODO: johbo: Make part of ac-tests
202 204 if [ ! -f rhodecode/public/js/scripts.js ]; then
203 205 echo "Missing scripts.js"
204 206 exit 1
205 207 fi
206 208 if [ ! -f rhodecode/public/css/style.css ]; then
207 209 echo "Missing style.css"
208 210 exit 1
209 211 fi
210 212 '';
211 213
212 214 });
213 215
214 216 rhodecode-testdata = import "${rhodecode-testdata-src}/default.nix" {
215 217 inherit
216 218 doCheck
217 219 pkgs
218 220 pythonPackages;
219 221 };
220 222
221 223 };
222 224
223 225 rhodecode-testdata-src = sources.rhodecode-testdata or (
224 226 pkgs.fetchhg {
225 227 url = "https://code.rhodecode.com/upstream/rc_testdata";
226 228 rev = "v0.9.0";
227 229 sha256 = "0k0ccb7cncd6mmzwckfbr6l7fsymcympwcm948qc3i0f0m6bbg1y";
228 230 });
229 231
230 232 # Apply all overrides and fix the final package set
231 233 myPythonPackagesUnfix = with pkgs.lib;
232 234 (extends pythonExternalOverrides
233 235 (extends pythonLocalOverrides
234 236 (extends pythonOverrides
235 237 pythonGeneratedPackages)));
236 238 myPythonPackages = (pkgs.lib.fix myPythonPackagesUnfix);
237 239
238 240 in myPythonPackages.rhodecode-enterprise-ce
@@ -1,177 +1,183 b''
1 1 # Makefile for Sphinx documentation
2 2 #
3 3
4 4 # You can set these variables from the command line.
5 5 SPHINXOPTS =
6 6 SPHINXBUILD = ./result/bin/sphinx-build
7 7 PAPER =
8 8 BUILDDIR = _build
9 9
10 10 # User-friendly check for sphinx-build
11 11 ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 12 $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13 13 endif
14 14
15 15 # Internal variables.
16 16 PAPEROPT_a4 = -D latex_paper_size=a4
17 17 PAPEROPT_letter = -D latex_paper_size=letter
18 18 ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
19 19 # the i18n builder cannot share the environment and doctrees with the others
20 20 I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
21 21
22 22 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23 23
24 24 help:
25 25 @echo "Please use \`make <target>' where <target> is one of"
26 26 @echo " html to make standalone HTML files"
27 27 @echo " dirhtml to make HTML files named index.html in directories"
28 28 @echo " singlehtml to make a single large HTML file"
29 29 @echo " pickle to make pickle files"
30 30 @echo " json to make JSON files"
31 31 @echo " htmlhelp to make HTML files and a HTML help project"
32 32 @echo " qthelp to make HTML files and a qthelp project"
33 33 @echo " devhelp to make HTML files and a Devhelp project"
34 34 @echo " epub to make an epub"
35 35 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36 36 @echo " latexpdf to make LaTeX files and run them through pdflatex"
37 37 @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38 38 @echo " text to make text files"
39 39 @echo " man to make manual pages"
40 40 @echo " texinfo to make Texinfo files"
41 41 @echo " info to make Texinfo files and run them through makeinfo"
42 42 @echo " gettext to make PO message catalogs"
43 43 @echo " changes to make an overview of all changed/added/deprecated items"
44 44 @echo " xml to make Docutils-native XML files"
45 45 @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46 46 @echo " linkcheck to check all external links for integrity"
47 47 @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48 48
49 49 clean:
50 50 rm -rf $(BUILDDIR)/*
51 51
52 cleanup:
53 @echo "cleaning build dir"
54 rm -rf $(BUILDDIR)/*
55 @echo "cleaning result symlink"
56 rm -v result
57
52 58 html:
53 59 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54 60 @echo
55 61 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56 62
57 63 dirhtml:
58 64 $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59 65 @echo
60 66 @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61 67
62 68 singlehtml:
63 69 $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64 70 @echo
65 71 @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66 72
67 73 pickle:
68 74 $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69 75 @echo
70 76 @echo "Build finished; now you can process the pickle files."
71 77
72 78 json:
73 79 $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74 80 @echo
75 81 @echo "Build finished; now you can process the JSON files."
76 82
77 83 htmlhelp:
78 84 $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79 85 @echo
80 86 @echo "Build finished; now you can run HTML Help Workshop with the" \
81 87 ".hhp project file in $(BUILDDIR)/htmlhelp."
82 88
83 89 qthelp:
84 90 $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85 91 @echo
86 92 @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87 93 ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88 94 @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/RhodeCodeInstaller.qhcp"
89 95 @echo "To view the help file:"
90 96 @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/RhodeCodeInstaller.qhc"
91 97
92 98 devhelp:
93 99 $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94 100 @echo
95 101 @echo "Build finished."
96 102 @echo "To view the help file:"
97 103 @echo "# mkdir -p $$HOME/.local/share/devhelp/RhodeCodeInstaller"
98 104 @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/RhodeCodeInstaller"
99 105 @echo "# devhelp"
100 106
101 107 epub:
102 108 $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103 109 @echo
104 110 @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105 111
106 112 latex:
107 113 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108 114 @echo
109 115 @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110 116 @echo "Run \`make' in that directory to run these through (pdf)latex" \
111 117 "(use \`make latexpdf' here to do that automatically)."
112 118
113 119 latexpdf:
114 120 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115 121 @echo "Running LaTeX files through pdflatex..."
116 122 $(MAKE) -C $(BUILDDIR)/latex all-pdf
117 123 @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118 124
119 125 latexpdfja:
120 126 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121 127 @echo "Running LaTeX files through platex and dvipdfmx..."
122 128 $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123 129 @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124 130
125 131 text:
126 132 $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127 133 @echo
128 134 @echo "Build finished. The text files are in $(BUILDDIR)/text."
129 135
130 136 man:
131 137 $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132 138 @echo
133 139 @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134 140
135 141 texinfo:
136 142 $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137 143 @echo
138 144 @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139 145 @echo "Run \`make' in that directory to run these through makeinfo" \
140 146 "(use \`make info' here to do that automatically)."
141 147
142 148 info:
143 149 $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144 150 @echo "Running Texinfo files through makeinfo..."
145 151 make -C $(BUILDDIR)/texinfo info
146 152 @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147 153
148 154 gettext:
149 155 $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150 156 @echo
151 157 @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152 158
153 159 changes:
154 160 $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155 161 @echo
156 162 @echo "The overview file is in $(BUILDDIR)/changes."
157 163
158 164 linkcheck:
159 165 $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160 166 @echo
161 167 @echo "Link check complete; look for any errors in the above output " \
162 168 "or in $(BUILDDIR)/linkcheck/output.txt."
163 169
164 170 doctest:
165 171 $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166 172 @echo "Testing of doctests in the sources finished, look at the " \
167 173 "results in $(BUILDDIR)/doctest/output.txt."
168 174
169 175 xml:
170 176 $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171 177 @echo
172 178 @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173 179
174 180 pseudoxml:
175 181 $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176 182 @echo
177 183 @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
@@ -1,114 +1,87 b''
1 1 .. _apache-conf-eg:
2 2
3 Apache Configuration Examples
4 -----------------------------
3 Apache Configuration Example
4 ----------------------------
5
6 Use the following example to configure Apache as a your web server.
7 Below config if for an Apache Reverse Proxy configuration.
8
9 .. note::
10
11 Apache requires the following modules to be enabled. Below is an example
12 how to enable them on Ubuntu Server
13
5 14
6 Use the following example to securely configure your Apache HTTP virtual hosts
7 file.
15 .. code-block:: bash
16
17 $ sudo a2enmod proxy
18 $ sudo a2enmod proxy_http
19 $ sudo a2enmod proxy_balancer
20 $ sudo a2enmod headers
21 $ sudo a2enmod ssl
22 $ sudo a2enmod rewrite
23
24 # requires Apache 2.4+, required to handle websockets/channelstream
25 $ sudo a2enmod proxy_wstunnel
26
8 27
9 28 .. code-block:: apache
10 29
30 ## HTTP to HTTPS rewrite
11 31 <VirtualHost *:80>
12 ServerName hg.myserver.com
13 ServerAlias hg.myserver.com
32 ServerName rhodecode.myserver.com
33 DocumentRoot /var/www/html
34 Redirect permanent / https://rhodecode.myserver.com/
35 </VirtualHost>
36
37 ## MAIN SSL enabled server
38 <VirtualHost *:443>
39
40 ServerName rhodecode.myserver.com
41 ServerAlias rhodecode.myserver.com
42
43 ## serve static files by Apache, recommended for performance
44 #Alias /_static /home/ubuntu/.rccontrol/community-1/static
45
46 RequestHeader set X-Forwarded-Proto "https"
47
48 ## channelstream websocket handling
49 ProxyPass /_channelstream ws://localhost:9800
50 ProxyPassReverse /_channelstream ws://localhost:9800
14 51
15 52 <Proxy *>
16 53 Order allow,deny
17 54 Allow from all
18 55 </Proxy>
19 56
20 # important !
21 # Directive to properly generate url (clone url) for pylons
22
57 # Directive to properly generate url (clone url) for RhodeCode
23 58 ProxyPreserveHost On
24 59
25 #rhodecode instance
26 ProxyPass / http://127.0.0.1:5000/
27 ProxyPassReverse / http://127.0.0.1:5000/
60 # Url to running RhodeCode instance. This is shown as `- URL:` when
61 # running rccontrol status.
62 ProxyPass / http://127.0.0.1:10002/
63 ProxyPassReverse / http://127.0.0.1:10002/
28 64
29 # Set strict HTTPS
65 # strict http prevents from https -> http downgrade
30 66 Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
31 67
32 68 # Set x-frame options
33 69 Header always append X-Frame-Options SAMEORIGIN
34 70
35 71 # To enable https use line below
36 72 # SetEnvIf X-Url-Scheme https HTTPS=1
37 73
38 # Secure your Diffie-hellmann deployment
74 # SSL setup
75 SSLEngine On
76 SSLCertificateFile /etc/apache2/ssl/rhodecode.myserver.pem
77 SSLCertificateKeyFile /etc/apache2/ssl/rhodecode.myserver.key
78
39 79 SSLProtocol all -SSLv2 -SSLv3
40 80 SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
41 81 SSLHonorCipherOrder on
42 SSLOpenSSLConfCmd DHParameters "{path to dhparams.pem}"
82
83 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
84 #SSLOpenSSLConfCmd DHParameters "/etc/apache2/dhparam.pem"
43 85
44 86 </VirtualHost>
45 87
46 Use the following example to configure Apache for a multi-node setup. The
47 timeout setting should be increased if you experience timeouts when working
48 with large |repos|.
49
50 .. code-block:: apache
51
52 #
53 # Timeout: The number of seconds before receives and sends time out.
54 #
55 Timeout 600
56
57 <VirtualHost *:80>
58
59 ProxyRequests off
60
61 #important !
62 #Directive to properly generate url (clone url) for pylons
63 ProxyPreserveHost On
64
65 ServerName your.rce.com
66 ServerAlias your.rce.com
67
68 <Proxy balancer://mycluster>
69 # WebHead1
70 BalancerMember http://10.58.1.171:10002 route=1
71 # WebHead2
72 BalancerMember http://10.58.1.172:10001 route=2
73
74 # Security "technically we aren't blocking
75 # anyone but this the place to make those
76 # chages
77 Order Deny,Allow
78 Deny from none
79 Allow from all
80
81 # Load Balancer Settings
82 # We will be configuring a simple Round
83 # Robin style load balancer. This means
84 # that all webheads take an equal share of
85 # of the load.
86 ProxySet stickysession=ROUTEID
87
88 </Proxy>
89
90 # balancer-manager
91 # This tool is built into the mod_proxy_balancer
92 # module and will allow you to do some simple
93 # modifications to the balanced group via a gui
94 # web interface.
95 <Location /balancer-manager>
96 SetHandler balancer-manager
97
98 # recommend locking this one down to your
99 # your office
100 Order deny,allow
101 Allow from all
102 </Location>
103
104 # Point of Balance
105 # This setting will allow to explicitly name the
106 # the location in the site that we want to be
107 # balanced, in this example we will balance "/"
108 # or everything in the site.
109 ProxyPass /balancer-manager !
110 ProxyPass / balancer://mycluster/
111
112 ProxyPassReverse / balancer://mycluster/
113
114 </VirtualHost>
@@ -1,15 +1,14 b''
1 1 .. _apache-ws-ref:
2 2
3 3 Apache HTTP Server Configuration
4 4 --------------------------------
5 5
6 6 To set up your Apache Web Server for optimal performance and security, use
7 7 the information in the following sections.
8 8
9 9 .. toctree::
10 10
11 11 apache-diffie-hellman
12 apache-conf-examples
12 apache-conf-example
13 13 apache-subdirectory
14 apache-reverse-proxy
15 14 apache-wsgi-coding
@@ -1,34 +1,35 b''
1 1 .. _apache-sub-ref:
2 2
3 3 Apache URL Prefix Configuration
4 4 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 5
6 6 Use the following example to configure Apache to use a URL prefix.
7 7
8 8 .. code-block:: apache
9 9
10 <Location /<someprefix>/ # Change <someprefix> into your chosen prefix
10 # Change someprefix into your chosen prefix
11 <Location /someprefix >
11 12 ProxyPreserveHost On
12 13 ProxyPass "http://127.0.0.1:5000/"
13 14 ProxyPassReverse "http://127.0.0.1:5000/"
14 15 Header set X-Url-Scheme https env=HTTPS
15 16 </Location>
16 17
17 18 In addition to the regular Apache setup you will need to add the following
18 19 lines into the ``rhodecode.ini`` file.
19 20
20 21 * Above ``[app:main]`` section of the ``rhodecode.ini`` file add the
21 22 following section if it doesn't exist yet.
22 23
23 24 .. code-block:: ini
24 25
25 26 [filter:proxy-prefix]
26 27 use = egg:PasteDeploy#prefix
27 28 prefix = /<someprefix> # Change <someprefix> into your chosen prefix
28 29
29 30 * In the the ``[app:main]`` section of your ``rhodecode.ini`` file add the
30 31 following line.
31 32
32 33 .. code-block:: ini
33 34
34 35 filter-with = proxy-prefix
@@ -1,120 +1,125 b''
1 1 Nginx Configuration Example
2 2 ---------------------------
3 3
4 4 Use the following example to configure Nginx as a your web server.
5 5
6
6 7 .. code-block:: nginx
7 8
8 9 log_format log_custom '$remote_addr - $remote_user [$time_local] '
9 10 '"$request" $status $body_bytes_sent '
10 11 '"$http_referer" "$http_user_agent" '
11 12 '$request_time $upstream_response_time $pipe';
12 13
14 ## define upstream (local RhodeCode instance) to connect to
13 15 upstream rc {
14
16 # Url to running RhodeCode instance.
17 # This is shown as `- URL:` in output from rccontrol status.
15 18 server 127.0.0.1:10002;
16 19
17 20 # add more instances for load balancing
18 21 # server 127.0.0.1:10003;
19 22 # server 127.0.0.1:10004;
20 23 }
21 24
22 ## gist alias server, for serving nicer GIST urls
25 ## HTTP to HTTPS rewrite
26 server {
27 listen 80;
28 server_name rhodecode.myserver.com;
23 29
30 if ($http_host = rhodecode.myserver.com) {
31 rewrite (.*) https://rhodecode.myserver.com$1 permanent;
32 }
33 }
34
35 ## Optional gist alias server, for serving nicer GIST urls.
24 36 server {
25 37 listen 443;
26 38 server_name gist.myserver.com;
27 39 access_log /var/log/nginx/gist.access.log log_custom;
28 40 error_log /var/log/nginx/gist.error.log;
29 41
30 42 ssl on;
31 43 ssl_certificate gist.rhodecode.myserver.com.crt;
32 44 ssl_certificate_key gist.rhodecode.myserver.com.key;
33 45
34 46 ssl_session_timeout 5m;
35 47
36 48 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
37 49 ssl_prefer_server_ciphers on;
38 50 ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
39 51
52 # strict http prevents from https -> http downgrade
40 53 add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
41 54
42 55 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
43 56 #ssl_dhparam /etc/nginx/ssl/dhparam.pem;
44 57
45 58 rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1;
46 59 rewrite (.*) https://rhodecode.myserver.com/_admin/gists;
47 60 }
48 61
49 ## HTTP to HTTPS rewrite
50 server {
51 listen 80;
52 server_name rhodecode.myserver.com;
53
54 if ($http_host = rhodecode.myserver.com) {
55 rewrite (.*) https://rhodecode.myserver.com$1 permanent;
56 }
57 }
58 62
59 63 ## MAIN SSL enabled server
60 64 server {
61 65 listen 443 ssl;
62 66 server_name rhodecode.myserver.com;
63 67
64 68 access_log /var/log/nginx/rhodecode.access.log log_custom;
65 69 error_log /var/log/nginx/rhodecode.error.log;
66 70
67 71 ssl on;
68 72 ssl_certificate rhodecode.myserver.com.crt;
69 73 ssl_certificate_key rhodecode.myserver.com.key;
70 74
71 75 ssl_session_timeout 5m;
72 76
73 77 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
74 78 ssl_prefer_server_ciphers on;
75 79 ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
76 80
77 81 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
78 82 #ssl_dhparam /etc/nginx/ssl/dhparam.pem;
79 83
80 84 include /etc/nginx/proxy.conf;
81 85
82 ## serve static files by nginx, recommended
86 ## serve static files by Nginx, recommended for performance
83 87 # location /_static/rhodecode {
84 88 # alias /path/to/.rccontrol/enterprise-1/static;
85 89 # }
86 90
87 ## channel stream live components
91 ## channelstream websocket handling
88 92 location /_channelstream {
89 93 rewrite /_channelstream/(.*) /$1 break;
94
90 95 proxy_pass http://127.0.0.1:9800;
91 96
92 97 proxy_connect_timeout 10;
93 98 proxy_send_timeout 10m;
94 99 proxy_read_timeout 10m;
95 100 tcp_nodelay off;
96 101 proxy_set_header Host $host;
97 102 proxy_set_header X-Real-IP $remote_addr;
98 103 proxy_set_header X-Url-Scheme $scheme;
99 104 proxy_set_header X-Forwarded-Proto $scheme;
100 105 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
101 106 gzip off;
102 107 proxy_http_version 1.1;
103 108 proxy_set_header Upgrade $http_upgrade;
104 109 proxy_set_header Connection "upgrade";
105 110 }
106 111
107 112 location / {
108 113 try_files $uri @rhode;
109 114 }
110 115
111 116 location @rhode {
112 117 proxy_pass http://rc;
113 118 }
114 119
115 120 ## custom 502 error page
116 121 error_page 502 /502.html;
117 122 location = /502.html {
118 123 root /path/to/.rccontrol/enterprise-1/static;
119 124 }
120 125 } No newline at end of file
@@ -1,14 +1,14 b''
1 1 .. _nginx-ws-ref:
2 2
3 Nginx Configuration
4 ===================
3 Nginx HTTP Server Configuration
4 -------------------------------
5 5
6 6 To set up your Nginx Web Server for optimal performance and security, use
7 7 the information in the following sections.
8 8
9 9 .. toctree::
10 10
11 11 nginx-diffie-hellman
12 12 nginx-config-example
13 13 nginx-tuning
14 14 nginx-url-prefix
@@ -1,119 +1,151 b''
1 1 .. _rhodecode-reset-ref:
2 2
3 3 Settings Management
4 4 -------------------
5 5
6 6 All |RCE| settings can be set from the user interface, but in the event that
7 7 it somehow becomes unavailable you can use ``ishell`` inside your |RCE|
8 8 ``virtualenv`` to carry out emergency measures.
9 9
10 10 .. warning::
11 11
12 12 Logging into the |RCE| database with ``iShell`` should only be done by an
13 13 experienced and knowledgeable database administrator.
14 14
15
15 16 Reset Admin Account Privileges
16 17 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17 18
18 19 If you accidentally remove your admin privileges from the admin account you
19 20 can restore them using ``ishell``. Use the following example to reset your
20 21 account permissions.
21 22
22 23 .. code-block:: bash
23 24
24 25 # Open iShell from the terminal
25 $ .rccontrol/enterprise-1/profile/bin/paster \
26 ishell .rccontrol/enterprise-1/rhodecode.ini
26 $ rccontrol ishell enterprise-1
27 27
28 28 .. code-block:: mysql
29 29
30 30 # Use this example to change user permissions
31 31 In [1]: adminuser = User.get_by_username('username')
32 32 In [2]: adminuser.admin = True
33 33 In [3]: Session().add(adminuser);Session().commit()
34 34 In [4]: exit()
35 35
36
36 37 Set to read global ``.hgrc`` file
37 38 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38 39
39 40 By default, |RCE| does not read global ``hgrc`` files in
40 41 ``/etc/mercurial/hgrc`` or ``/etc/mercurial/hgrc.d`` because it
41 42 can lead to issues. This is set in the ``rhodecode_ui`` table for which
42 43 there is no UI. If you need to edit this you can
43 44 manually change the settings using SQL statements with ``ishell``. Use the
44 45 following example to make changes to this table.
45 46
46 47 .. code-block:: bash
47 48
48 49 # Open iShell from the terminal
49 $ .rccontrol/enterprise-5/profile/bin/paster \
50 ishell.rccontrol/enterprise-5/rhodecode.ini
50 $ rccontrol ishell enterprise-1
51 51
52 52 .. code-block:: mysql
53 53
54 54 # Use this example to enable global .hgrc access
55 55 In [1]: new_option = RhodeCodeUi()
56 56 In [2]: new_option.ui_section='web'
57 57 In [3]: new_option.ui_key='allow_push'
58 58 In [4]: new_option.ui_value='*'
59 59 In [5]: Session().add(new_option);Session().commit()
60 60 In [6]: exit()
61 61
62
62 63 Manually Reset Password
63 64 ^^^^^^^^^^^^^^^^^^^^^^^
64 65
65 66 If you need to manually reset a user password, use the following steps.
66 67
67 68 1. Navigate to your |RCE| install location.
68 69 2. Run the interactive ``ishell`` prompt.
69 70 3. Set a new password.
70 71
71 72 Use the following code example to carry out these steps.
72 73
73 74 .. code-block:: bash
74 75
75 76 # starts the ishell interactive prompt
76 $ .rccontrol/enterprise-1/profile/bin/paster \
77 ishell .rccontrol/enterprise-1/rhodecode.ini
77 $ rccontrol ishell enterprise-1
78 78
79 79 .. code-block:: mysql
80 80
81 81 In [1]: from rhodecode.lib.auth import generate_auth_token
82 82 In [2]: from rhodecode.lib.auth import get_crypt_password
83 83 # Enter the user name whose password you wish to change
84 84 In [3]: my_user = 'USERNAME'
85 85 In [4]: u = User.get_by_username(my_user)
86 86 # If this fails then the user does not exist
87 87 In [5]: u.auth_token = generate_auth_token(my_user)
88 88 # Set the new password
89 89 In [6]: u.password = get_crypt_password('PASSWORD')
90 90 In [7]: Session().add(u);Session().commit()
91 91 In [8]: exit()
92 92
93 93
94
95 94 Change user details
96 95 ^^^^^^^^^^^^^^^^^^^
97 96
98 97 If you need to manually change some of users details, use the following steps.
99 98
100 99 1. Navigate to your |RCE| install location.
101 100 2. Run the interactive ``ishell`` prompt.
102 101 3. Set a new arguments for users.
103 102
104 103 Use the following code example to carry out these steps.
105 104
106 105 .. code-block:: bash
107 106
108 107 # starts the ishell interactive prompt
109 $ .rccontrol/enterprise-1/profile/bin/paster \
110 ishell .rccontrol/enterprise-1/rhodecode.ini
108 $ rccontrol ishell enterprise-1
111 109
112 110 .. code-block:: mysql
113 111
114 112 # Use this example to change email and username of LDAP user
115 113 In [1]: my_user = User.get_by_username('some_username')
116 114 In [2]: my_user.email = 'new_email@foobar.com'
117 115 In [3]: my_user.username = 'SomeUser'
118 116 In [4]: Session().add(my_user);Session().commit()
119 117 In [5]: exit()
118
119
120 Change user login type
121 ^^^^^^^^^^^^^^^^^^^^^^
122
123 Sometimes it's required to change account type from RhodeCode to LDAP or
124 other external authentication type.
125 If you need to manually change the method of login, use the following steps.
126
127 1. Navigate to your |RCE| install location.
128 2. Run the interactive ``ishell`` prompt.
129 3. Set a new arguments for users.
130
131 Use the following code example to carry out these steps.
132 Available values for new_extern_type can be found when browsing available
133 authentication types in RhodeCode admin interface for authentication.
134 Use the text which is shown after '#' sign, eg.
135 ` LDAP (egg:rhodecode-enterprise-ce#ldap)` it's type is 'ldap'
136
137 .. code-block:: bash
138
139 # starts the ishell interactive prompt
140 $ rccontrol ishell enterprise-1
141
142 .. code-block:: mysql
143
144 # Use this example to change users from authentication
145 # using rhodecode internal to ldap
146 In [1]: new_extern_type = 'ldap'
147 In [2]: my_user = User.get_by_username('some_username')
148 In [3]: my_user.extern_type = new_extern_type
149 In [4]: my_user.extern_name = new_extern_type
150 In [5]: Session().add(my_user);Session().commit()
151 In [6]: exit()
@@ -1,137 +1,138 b''
1 1 .. _svn-http:
2 2
3 3 |svn| With Write Over HTTP
4 4 ^^^^^^^^^^^^^^^^^^^^^^^^^^
5 5
6 6 To use |svn| with read/write support over the |svn| HTTP protocol, you have to
7 7 configure the HTTP |svn| backend.
8 8
9 9 Prerequisites
10 10 =============
11 11
12 12 - Enable HTTP support inside the admin VCS settings on your |RCE| instance
13 13 - You need to install the following tools on the machine that is running an
14 14 instance of |RCE|:
15 15 ``Apache HTTP Server`` and ``mod_dav_svn``.
16 16
17 17
18 18 Using Ubuntu 14.04 Distribution as an example execute the following:
19 19
20 20 .. code-block:: bash
21 21
22 22 $ sudo apt-get install apache2 libapache2-mod-svn
23 23
24 24 Once installed you need to enable ``dav_svn``:
25 25
26 26 .. code-block:: bash
27 27
28 28 $ sudo a2enmod dav_svn
29 29 $ sudo a2enmod headers
30 $ sudo a2enmod authn_anon
30 31
31 32
32 33 Configuring Apache Setup
33 34 ========================
34 35
35 36 .. tip::
36 37
37 38 It is recommended to run Apache on a port other than 80, due to possible
38 39 conflicts with other HTTP servers like nginx. To do this, set the
39 40 ``Listen`` parameter in the ``/etc/apache2/ports.conf`` file, for example
40 41 ``Listen 8090``.
41 42
42 43
43 44 .. warning::
44 45
45 46 Make sure your Apache instance which runs the mod_dav_svn module is
46 47 only accessible by |RCE|. Otherwise everyone is able to browse
47 48 the repositories or run subversion operations (checkout/commit/etc.).
48 49
49 50 It is also recommended to run apache as the same user as |RCE|, otherwise
50 51 permission issues could occur. To do this edit the ``/etc/apache2/envvars``
51 52
52 53 .. code-block:: apache
53 54
54 55 export APACHE_RUN_USER=rhodecode
55 56 export APACHE_RUN_GROUP=rhodecode
56 57
57 58 1. To configure Apache, create and edit a virtual hosts file, for example
58 :file:`/etc/apache2/sites-available/default.conf`. Below is an example
59 :file:`/etc/apache2/sites-enabled/default.conf`. Below is an example
59 60 how to use one with auto-generated config ```mod_dav_svn.conf```
60 61 from configured |RCE| instance.
61 62
62 63 .. code-block:: apache
63 64
64 65 <VirtualHost *:8090>
65 66 ServerAdmin rhodecode-admin@localhost
66 67 DocumentRoot /var/www/html
67 68 ErrorLog ${'${APACHE_LOG_DIR}'}/error.log
68 69 CustomLog ${'${APACHE_LOG_DIR}'}/access.log combined
69 70 Include /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf
70 71 </VirtualHost>
71 72
72 73
73 74 2. Go to the :menuselection:`Admin --> Settings --> VCS` page, and
74 75 enable :guilabel:`Proxy Subversion HTTP requests`, and specify the
75 76 :guilabel:`Subversion HTTP Server URL`.
76 77
77 78 3. Open the |RCE| configuration file,
78 79 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
79 80
80 81 4. Add the following configuration option in the ``[app:main]``
81 82 section if you don't have it yet.
82 83
83 84 This enables mapping of the created |RCE| repo groups into special
84 85 |svn| paths. Each time a new repository group is created, the system will
85 86 update the template file and create new mapping. Apache web server needs to
86 87 be reloaded to pick up the changes on this file.
87 88 To do this, simply configure `svn.proxy.reload_cmd` inside the .ini file.
88 89 Example configuration:
89 90
90 91
91 92 .. code-block:: ini
92 93
93 94 ############################################################
94 95 ### Subversion proxy support (mod_dav_svn) ###
95 96 ### Maps RhodeCode repo groups into SVN paths for Apache ###
96 97 ############################################################
97 98 ## Enable or disable the config file generation.
98 99 svn.proxy.generate_config = true
99 100 ## Generate config file with `SVNListParentPath` set to `On`.
100 101 svn.proxy.list_parent_path = true
101 102 ## Set location and file name of generated config file.
102 103 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
103 104 ## Used as a prefix to the <Location> block in the generated config file.
104 105 ## In most cases it should be set to `/`.
105 106 svn.proxy.location_root = /
106 107 ## Command to reload the mod dav svn configuration on change.
107 108 ## Example: `/etc/init.d/apache2 reload`
108 109 svn.proxy.reload_cmd = /etc/init.d/apache2 reload
109 110 ## If the timeout expires before the reload command finishes, the command will
110 111 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
111 112 #svn.proxy.reload_timeout = 10
112 113
113 114
114 115 This would create a special template file called ```mod_dav_svn.conf```. We
115 116 used that file path in the apache config above inside the Include statement.
116 117 It's also possible to generate the config from the
117 118 :menuselection:`Admin --> Settings --> VCS` page.
118 119
119 120
120 121 Using |svn|
121 122 ===========
122 123
123 124 Once |svn| has been enabled on your instance, you can use it with the
124 125 following examples. For more |svn| information, see the `Subversion Red Book`_
125 126
126 127 .. code-block:: bash
127 128
128 129 # To clone a repository
129 130 svn checkout http://my-svn-server.example.com/my-svn-repo
130 131
131 132 # svn commit
132 133 svn commit
133 134
134 135
135 136 .. _Subversion Red Book: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.ref.svn
136 137
137 138 .. _Ask Ubuntu: http://askubuntu.com/questions/162391/how-do-i-fix-my-locale-issue No newline at end of file
@@ -1,32 +1,32 b''
1 1 .. _hg-lrg-loc:
2 2
3 3 Change the |hg| Large Files Location
4 4 ------------------------------------
5 5
6 6 |RCE| manages |hg| larges files from the following default location
7 7 :file:`/home/{user}/repos/.cache/largefiles`. If you wish to change this, use
8 8 the following steps:
9 9
10 10 1. Open ishell from the terminal and use it to log into the |RCE| database by
11 11 specifying the instance :file:`rhodecode.ini` file.
12 12
13 13 .. code-block:: bash
14 14
15 15 # Open iShell from the terminal and set ini file
16 $ .rccontrol/enterprise-1/profile/bin/paster ishell .rccontrol/enterprise-1/rhodecode.ini
16 $ rccontrol ishell enterprise-1
17 17
18 18 2. Run the following commands, and ensure that |RCE| has write access to the
19 19 new directory:
20 20
21 21 .. code-block:: bash
22 22
23 23 # Once logged into the database, use SQL to redirect
24 24 # the large files location
25 25 In [1]: from rhodecode.model.settings import SettingsModel
26 26 In [2]: SettingsModel().get_ui_by_key('usercache')
27 27 Out[2]: <RhodeCodeUi[largefiles]usercache=>/mnt/hgfs/shared/workspace/xxxx/.cache/largefiles]>
28 28
29 29 In [3]: largefiles_cache = SettingsModel().get_ui_by_key('usercache')
30 30 In [4]: largefiles_cache.ui_value = '/new/path’
31 31 In [5]: Session().add(largefiles_cache);Session().commit()
32 32
@@ -1,23 +1,8 b''
1 1 .. _db-session-ref:
2 2
3 3 Increase Database Performance
4 4 -----------------------------
5 5
6 To increase database performance switch to database-based user sessions.
7 File-based sessions are only suitable for smaller setups. The most common
8 issue being file limit errors which occur if there are lots of session files.
9 Therefore, in a large scale deployment, to give better performance,
10 scalability, and maintainability we recommend switching from file-based
11 sessions to database-based user sessions.
6 For tuning PostgreSQL we recommend reading: http://www.revsys.com/writings/postgresql-performance.html
12 7
13 To switch to database-based user sessions uncomment the following section in
14 your :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
15
16 .. code-block:: ini
17
18 # db session
19 beaker.session.type = ext:database
20
21 # adjust this property to include your database credentials
22 beaker.session.sa.url = postgresql://postgres:<pass>@localhost/rhodecode
23 beaker.session.table_name = db_session
8 For tuning MySQL we recommend reading: http://www.tecmint.com/mysql-mariadb-performance-tuning-and-optimization/ No newline at end of file
@@ -1,42 +1,42 b''
1 1 .. _data-mem:
2 2
3 3 Mount Cache Folders To Memory
4 4 -----------------------------
5 5
6 6 To increase the performance of folders containing cache data, you can mount
7 7 them to memory. The following folders specified in the :file:`rhodecode.ini`
8 8 file would benefit from this.
9 9
10 10 .. code-block:: ini
11 11
12 12 cache_dir = %(here)s/data
13 13 search.location = %(here)s/data/index
14 14
15 15 Use the following Ubuntu example to mount these to memory, or see your
16 16 particular |os| instructions. The expected performance benefit is
17 17 approximately 5%. You should ensure you allocate an adequate amount of memory
18 18 depending on your available resources.
19 19
20 20 .. code-block:: bash
21 21
22 22 # mount to memory with 2GB limit and 755 write permissions
23 23 mount -t tmpfs -o size=2G,mode=0755 tmpfs /home/user/.rccontrol/enterprise-1/data
24 24 mount -t tmpfs -o size=2G,mode=0755 tmpfs /home/user/.rccontrol/enterprise-1/data/index
25 25
26 26 .. _move-tmp:
27 27
28 28 Move ``tmp`` to TMPFS
29 29 ---------------------
30 30
31 31 |RCE| components heavily use the :file:`/tmp` folder, so moving your
32 32 :file:`/tmp` folder into to a RAM-based TMPS can lead to a noticeable
33 33 performance boost.
34 34
35 35 .. code-block:: bash
36 36
37 # mount tmp to memory with 2GB limit and 755 write permissions
38 mount -t tmpfs -o size=2G,mode=0755 tmpfs /tmp
37 # mount tmp to memory with 2GB limit and 1777 write permissions
38 mount -t tmpfs -o size=2G,mode=1777 tmpfs /tmp
39 39
40 40 For more information about TMPFS, see the documentation `here`_.
41 41
42 42 .. _here: https://wiki.archlinux.org/index.php/Tmpfs
@@ -1,20 +1,21 b''
1 1 .. _rhodecode-tuning-ref:
2 2
3 3 Tuning |RCE|
4 4 ============
5 5
6 6 To customize your |RCE| |version| installation for maximum performance you
7 7 may find some of the following methods useful.
8 8
9 9 .. toctree::
10 10
11 11 tuning-gunicorn
12 12 tuning-vcs-memory-cache
13 tuning-user-sessions-performance
13 14 tuning-increase-db-performance
14 15 tuning-scale-horizontally
15 16 tuning-increase-cache-size
16 17 tuning-mount-cache-memory
17 18 tuning-change-encoding
18 19 tuning-change-large-file-dir
19 20 tuning-hg-auth-loop
20 21
@@ -1,371 +1,376 b''
1 1 .. _pull-request-methods-ref:
2 2
3 3 pull_request methods
4 4 ====================
5 5
6 6 close_pull_request
7 7 ------------------
8 8
9 9 .. py:function:: close_pull_request(apiuser, repoid, pullrequestid, userid=<Optional:<OptionalAttr:apiuser>>)
10 10
11 11 Close the pull request specified by `pullrequestid`.
12 12
13 13 :param apiuser: This is filled automatically from the |authtoken|.
14 14 :type apiuser: AuthUser
15 15 :param repoid: Repository name or repository ID to which the pull
16 16 request belongs.
17 17 :type repoid: str or int
18 18 :param pullrequestid: ID of the pull request to be closed.
19 19 :type pullrequestid: int
20 20 :param userid: Close the pull request as this user.
21 21 :type userid: Optional(str or int)
22 22
23 23 Example output:
24 24
25 25 .. code-block:: bash
26 26
27 27 "id": <id_given_in_input>,
28 28 "result":
29 29 {
30 30 "pull_request_id": "<int>",
31 31 "closed": "<bool>"
32 32 },
33 33 "error": null
34 34
35 35
36 36 comment_pull_request
37 37 --------------------
38 38
39 .. py:function:: comment_pull_request(apiuser, repoid, pullrequestid, message=<Optional:None>, status=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
39 .. py:function:: comment_pull_request(apiuser, repoid, pullrequestid, message=<Optional:None>, commit_id=<Optional:None>, status=<Optional:None>, comment_type=<Optional:u'note'>, resolves_comment_id=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
40 40
41 41 Comment on the pull request specified with the `pullrequestid`,
42 42 in the |repo| specified by the `repoid`, and optionally change the
43 43 review status.
44 44
45 45 :param apiuser: This is filled automatically from the |authtoken|.
46 46 :type apiuser: AuthUser
47 47 :param repoid: The repository name or repository ID.
48 48 :type repoid: str or int
49 49 :param pullrequestid: The pull request ID.
50 50 :type pullrequestid: int
51 :param commit_id: Specify the commit_id for which to set a comment. If
52 given commit_id is different than latest in the PR status
53 change won't be performed.
54 :type commit_id: str
51 55 :param message: The text content of the comment.
52 56 :type message: str
53 57 :param status: (**Optional**) Set the approval status of the pull
54 request. Valid options are:
55 * not_reviewed
56 * approved
57 * rejected
58 * under_review
58 request. One of: 'not_reviewed', 'approved', 'rejected',
59 'under_review'
59 60 :type status: str
61 :param comment_type: Comment type, one of: 'note', 'todo'
62 :type comment_type: Optional(str), default: 'note'
60 63 :param userid: Comment on the pull request as this user
61 64 :type userid: Optional(str or int)
62 65
63 66 Example output:
64 67
65 68 .. code-block:: bash
66 69
67 70 id : <id_given_in_input>
68 71 result :
69 72 {
70 73 "pull_request_id": "<Integer>",
71 "comment_id": "<Integer>"
74 "comment_id": "<Integer>",
75 "status": {"given": <given_status>,
76 "was_changed": <bool status_was_actually_changed> },
72 77 }
73 78 error : null
74 79
75 80
76 81 create_pull_request
77 82 -------------------
78 83
79 84 .. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, title, description=<Optional:''>, reviewers=<Optional:None>)
80 85
81 86 Creates a new pull request.
82 87
83 88 Accepts refs in the following formats:
84 89
85 90 * branch:<branch_name>:<sha>
86 91 * branch:<branch_name>
87 92 * bookmark:<bookmark_name>:<sha> (Mercurial only)
88 93 * bookmark:<bookmark_name> (Mercurial only)
89 94
90 95 :param apiuser: This is filled automatically from the |authtoken|.
91 96 :type apiuser: AuthUser
92 97 :param source_repo: Set the source repository name.
93 98 :type source_repo: str
94 99 :param target_repo: Set the target repository name.
95 100 :type target_repo: str
96 101 :param source_ref: Set the source ref name.
97 102 :type source_ref: str
98 103 :param target_ref: Set the target ref name.
99 104 :type target_ref: str
100 105 :param title: Set the pull request title.
101 106 :type title: str
102 107 :param description: Set the pull request description.
103 108 :type description: Optional(str)
104 109 :param reviewers: Set the new pull request reviewers list.
105 110 :type reviewers: Optional(list)
106 111 Accepts username strings or objects of the format:
107 112 {
108 113 'username': 'nick', 'reasons': ['original author']
109 114 }
110 115
111 116
112 117 get_pull_request
113 118 ----------------
114 119
115 120 .. py:function:: get_pull_request(apiuser, repoid, pullrequestid)
116 121
117 122 Get a pull request based on the given ID.
118 123
119 124 :param apiuser: This is filled automatically from the |authtoken|.
120 125 :type apiuser: AuthUser
121 126 :param repoid: Repository name or repository ID from where the pull
122 127 request was opened.
123 128 :type repoid: str or int
124 129 :param pullrequestid: ID of the requested pull request.
125 130 :type pullrequestid: int
126 131
127 132 Example output:
128 133
129 134 .. code-block:: bash
130 135
131 136 "id": <id_given_in_input>,
132 137 "result":
133 138 {
134 139 "pull_request_id": "<pull_request_id>",
135 140 "url": "<url>",
136 141 "title": "<title>",
137 142 "description": "<description>",
138 143 "status" : "<status>",
139 144 "created_on": "<date_time_created>",
140 145 "updated_on": "<date_time_updated>",
141 146 "commit_ids": [
142 147 ...
143 148 "<commit_id>",
144 149 "<commit_id>",
145 150 ...
146 151 ],
147 152 "review_status": "<review_status>",
148 153 "mergeable": {
149 154 "status": "<bool>",
150 155 "message": "<message>",
151 156 },
152 157 "source": {
153 158 "clone_url": "<clone_url>",
154 159 "repository": "<repository_name>",
155 160 "reference":
156 161 {
157 162 "name": "<name>",
158 163 "type": "<type>",
159 164 "commit_id": "<commit_id>",
160 165 }
161 166 },
162 167 "target": {
163 168 "clone_url": "<clone_url>",
164 169 "repository": "<repository_name>",
165 170 "reference":
166 171 {
167 172 "name": "<name>",
168 173 "type": "<type>",
169 174 "commit_id": "<commit_id>",
170 175 }
171 176 },
172 177 "merge": {
173 178 "clone_url": "<clone_url>",
174 179 "reference":
175 180 {
176 181 "name": "<name>",
177 182 "type": "<type>",
178 183 "commit_id": "<commit_id>",
179 184 }
180 185 },
181 186 "author": <user_obj>,
182 187 "reviewers": [
183 188 ...
184 189 {
185 190 "user": "<user_obj>",
186 191 "review_status": "<review_status>",
187 192 }
188 193 ...
189 194 ]
190 195 },
191 196 "error": null
192 197
193 198
194 199 get_pull_requests
195 200 -----------------
196 201
197 202 .. py:function:: get_pull_requests(apiuser, repoid, status=<Optional:'new'>)
198 203
199 204 Get all pull requests from the repository specified in `repoid`.
200 205
201 206 :param apiuser: This is filled automatically from the |authtoken|.
202 207 :type apiuser: AuthUser
203 208 :param repoid: Repository name or repository ID.
204 209 :type repoid: str or int
205 210 :param status: Only return pull requests with the specified status.
206 211 Valid options are.
207 212 * ``new`` (default)
208 213 * ``open``
209 214 * ``closed``
210 215 :type status: str
211 216
212 217 Example output:
213 218
214 219 .. code-block:: bash
215 220
216 221 "id": <id_given_in_input>,
217 222 "result":
218 223 [
219 224 ...
220 225 {
221 226 "pull_request_id": "<pull_request_id>",
222 227 "url": "<url>",
223 228 "title" : "<title>",
224 229 "description": "<description>",
225 230 "status": "<status>",
226 231 "created_on": "<date_time_created>",
227 232 "updated_on": "<date_time_updated>",
228 233 "commit_ids": [
229 234 ...
230 235 "<commit_id>",
231 236 "<commit_id>",
232 237 ...
233 238 ],
234 239 "review_status": "<review_status>",
235 240 "mergeable": {
236 241 "status": "<bool>",
237 242 "message: "<message>",
238 243 },
239 244 "source": {
240 245 "clone_url": "<clone_url>",
241 246 "reference":
242 247 {
243 248 "name": "<name>",
244 249 "type": "<type>",
245 250 "commit_id": "<commit_id>",
246 251 }
247 252 },
248 253 "target": {
249 254 "clone_url": "<clone_url>",
250 255 "reference":
251 256 {
252 257 "name": "<name>",
253 258 "type": "<type>",
254 259 "commit_id": "<commit_id>",
255 260 }
256 261 },
257 262 "merge": {
258 263 "clone_url": "<clone_url>",
259 264 "reference":
260 265 {
261 266 "name": "<name>",
262 267 "type": "<type>",
263 268 "commit_id": "<commit_id>",
264 269 }
265 270 },
266 271 "author": <user_obj>,
267 272 "reviewers": [
268 273 ...
269 274 {
270 275 "user": "<user_obj>",
271 276 "review_status": "<review_status>",
272 277 }
273 278 ...
274 279 ]
275 280 }
276 281 ...
277 282 ],
278 283 "error": null
279 284
280 285
281 286 merge_pull_request
282 287 ------------------
283 288
284 289 .. py:function:: merge_pull_request(apiuser, repoid, pullrequestid, userid=<Optional:<OptionalAttr:apiuser>>)
285 290
286 291 Merge the pull request specified by `pullrequestid` into its target
287 292 repository.
288 293
289 294 :param apiuser: This is filled automatically from the |authtoken|.
290 295 :type apiuser: AuthUser
291 296 :param repoid: The Repository name or repository ID of the
292 297 target repository to which the |pr| is to be merged.
293 298 :type repoid: str or int
294 299 :param pullrequestid: ID of the pull request which shall be merged.
295 300 :type pullrequestid: int
296 301 :param userid: Merge the pull request as this user.
297 302 :type userid: Optional(str or int)
298 303
299 304 Example output:
300 305
301 306 .. code-block:: bash
302 307
303 308 "id": <id_given_in_input>,
304 309 "result":
305 310 {
306 311 "executed": "<bool>",
307 312 "failure_reason": "<int>",
308 313 "merge_commit_id": "<merge_commit_id>",
309 314 "possible": "<bool>",
310 315 "merge_ref": {
311 316 "commit_id": "<commit_id>",
312 317 "type": "<type>",
313 318 "name": "<name>"
314 319 }
315 320 },
316 321 "error": null
317 322
318 323
319 324 update_pull_request
320 325 -------------------
321 326
322 327 .. py:function:: update_pull_request(apiuser, repoid, pullrequestid, title=<Optional:''>, description=<Optional:''>, reviewers=<Optional:None>, update_commits=<Optional:None>, close_pull_request=<Optional:None>)
323 328
324 329 Updates a pull request.
325 330
326 331 :param apiuser: This is filled automatically from the |authtoken|.
327 332 :type apiuser: AuthUser
328 333 :param repoid: The repository name or repository ID.
329 334 :type repoid: str or int
330 335 :param pullrequestid: The pull request ID.
331 336 :type pullrequestid: int
332 337 :param title: Set the pull request title.
333 338 :type title: str
334 339 :param description: Update pull request description.
335 340 :type description: Optional(str)
336 341 :param reviewers: Update pull request reviewers list with new value.
337 342 :type reviewers: Optional(list)
338 343 :param update_commits: Trigger update of commits for this pull request
339 344 :type: update_commits: Optional(bool)
340 345 :param close_pull_request: Close this pull request with rejected state
341 346 :type: close_pull_request: Optional(bool)
342 347
343 348 Example output:
344 349
345 350 .. code-block:: bash
346 351
347 352 id : <id_given_in_input>
348 353 result :
349 354 {
350 355 "msg": "Updated pull request `63`",
351 356 "pull_request": <pull_request_object>,
352 357 "updated_reviewers": {
353 358 "added": [
354 359 "username"
355 360 ],
356 361 "removed": []
357 362 },
358 363 "updated_commits": {
359 364 "added": [
360 365 "<sha1_hash>"
361 366 ],
362 367 "common": [
363 368 "<sha1_hash>",
364 369 "<sha1_hash>",
365 370 ],
366 371 "removed": []
367 372 }
368 373 }
369 374 error : null
370 375
371 376
@@ -1,990 +1,1000 b''
1 1 .. _repo-methods-ref:
2 2
3 3 repo methods
4 4 ============
5 5
6 6 add_field_to_repo
7 7 -----------------
8 8
9 9 .. py:function:: add_field_to_repo(apiuser, repoid, key, label=<Optional:''>, description=<Optional:''>)
10 10
11 11 Adds an extra field to a repository.
12 12
13 13 This command can only be run using an |authtoken| with at least
14 14 write permissions to the |repo|.
15 15
16 16 :param apiuser: This is filled automatically from the |authtoken|.
17 17 :type apiuser: AuthUser
18 18 :param repoid: Set the repository name or repository id.
19 19 :type repoid: str or int
20 20 :param key: Create a unique field key for this repository.
21 21 :type key: str
22 22 :param label:
23 23 :type label: Optional(str)
24 24 :param description:
25 25 :type description: Optional(str)
26 26
27 27
28 28 comment_commit
29 29 --------------
30 30
31 .. py:function:: comment_commit(apiuser, repoid, commit_id, message, userid=<Optional:<OptionalAttr:apiuser>>, status=<Optional:None>)
31 .. py:function:: comment_commit(apiuser, repoid, commit_id, message, status=<Optional:None>, comment_type=<Optional:u'note'>, resolves_comment_id=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
32 32
33 33 Set a commit comment, and optionally change the status of the commit.
34 34
35 35 :param apiuser: This is filled automatically from the |authtoken|.
36 36 :type apiuser: AuthUser
37 37 :param repoid: Set the repository name or repository ID.
38 38 :type repoid: str or int
39 39 :param commit_id: Specify the commit_id for which to set a comment.
40 40 :type commit_id: str
41 41 :param message: The comment text.
42 42 :type message: str
43 :param status: (**Optional**) status of commit, one of: 'not_reviewed',
44 'approved', 'rejected', 'under_review'
45 :type status: str
46 :param comment_type: Comment type, one of: 'note', 'todo'
47 :type comment_type: Optional(str), default: 'note'
43 48 :param userid: Set the user name of the comment creator.
44 49 :type userid: Optional(str or int)
45 :param status: status, one of 'not_reviewed', 'approved', 'rejected',
46 'under_review'
47 :type status: str
48 50
49 51 Example error output:
50 52
51 .. code-block:: json
53 .. code-block:: bash
52 54
53 55 {
54 56 "id" : <id_given_in_input>,
55 57 "result" : {
56 58 "msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
57 59 "status_change": null or <status>,
58 60 "success": true
59 61 },
60 62 "error" : null
61 63 }
62 64
63 65
64 66 create_repo
65 67 -----------
66 68
67 69 .. py:function:: create_repo(apiuser, repo_name, repo_type, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, copy_permissions=<Optional:False>)
68 70
69 71 Creates a repository.
70 72
71 73 * If the repository name contains "/", repository will be created inside
72 74 a repository group or nested repository groups
73 75
74 76 For example "foo/bar/repo1" will create |repo| called "repo1" inside
75 77 group "foo/bar". You have to have permissions to access and write to
76 78 the last repository group ("bar" in this example)
77 79
78 80 This command can only be run using an |authtoken| with at least
79 81 permissions to create repositories, or write permissions to
80 82 parent repository groups.
81 83
82 84 :param apiuser: This is filled automatically from the |authtoken|.
83 85 :type apiuser: AuthUser
84 86 :param repo_name: Set the repository name.
85 87 :type repo_name: str
86 88 :param repo_type: Set the repository type; 'hg','git', or 'svn'.
87 89 :type repo_type: str
88 90 :param owner: user_id or username
89 91 :type owner: Optional(str)
90 92 :param description: Set the repository description.
91 93 :type description: Optional(str)
92 94 :param private: set repository as private
93 95 :type private: bool
94 96 :param clone_uri: set clone_uri
95 97 :type clone_uri: str
96 98 :param landing_rev: <rev_type>:<rev>
97 99 :type landing_rev: str
98 100 :param enable_locking:
99 101 :type enable_locking: bool
100 102 :param enable_downloads:
101 103 :type enable_downloads: bool
102 104 :param enable_statistics:
103 105 :type enable_statistics: bool
104 106 :param copy_permissions: Copy permission from group in which the
105 107 repository is being created.
106 108 :type copy_permissions: bool
107 109
108 110
109 111 Example output:
110 112
111 113 .. code-block:: bash
112 114
113 115 id : <id_given_in_input>
114 116 result: {
115 117 "msg": "Created new repository `<reponame>`",
116 118 "success": true,
117 119 "task": "<celery task id or None if done sync>"
118 120 }
119 121 error: null
120 122
121 123
122 124 Example error output:
123 125
124 126 .. code-block:: bash
125 127
126 128 id : <id_given_in_input>
127 129 result : null
128 130 error : {
129 131 'failed to create repository `<repo_name>`'
130 132 }
131 133
132 134
133 135 delete_repo
134 136 -----------
135 137
136 138 .. py:function:: delete_repo(apiuser, repoid, forks=<Optional:''>)
137 139
138 140 Deletes a repository.
139 141
140 142 * When the `forks` parameter is set it's possible to detach or delete
141 143 forks of deleted repository.
142 144
143 145 This command can only be run using an |authtoken| with admin
144 146 permissions on the |repo|.
145 147
146 148 :param apiuser: This is filled automatically from the |authtoken|.
147 149 :type apiuser: AuthUser
148 150 :param repoid: Set the repository name or repository ID.
149 151 :type repoid: str or int
150 152 :param forks: Set to `detach` or `delete` forks from the |repo|.
151 153 :type forks: Optional(str)
152 154
153 155 Example error output:
154 156
155 157 .. code-block:: bash
156 158
157 159 id : <id_given_in_input>
158 160 result: {
159 161 "msg": "Deleted repository `<reponame>`",
160 162 "success": true
161 163 }
162 164 error: null
163 165
164 166
165 167 fork_repo
166 168 ---------
167 169
168 170 .. py:function:: fork_repo(apiuser, repoid, fork_name, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, copy_permissions=<Optional:False>)
169 171
170 172 Creates a fork of the specified |repo|.
171 173
172 174 * If the fork_name contains "/", fork will be created inside
173 175 a repository group or nested repository groups
174 176
175 177 For example "foo/bar/fork-repo" will create fork called "fork-repo"
176 178 inside group "foo/bar". You have to have permissions to access and
177 179 write to the last repository group ("bar" in this example)
178 180
179 181 This command can only be run using an |authtoken| with minimum
180 182 read permissions of the forked repo, create fork permissions for an user.
181 183
182 184 :param apiuser: This is filled automatically from the |authtoken|.
183 185 :type apiuser: AuthUser
184 186 :param repoid: Set repository name or repository ID.
185 187 :type repoid: str or int
186 188 :param fork_name: Set the fork name, including it's repository group membership.
187 189 :type fork_name: str
188 190 :param owner: Set the fork owner.
189 191 :type owner: str
190 192 :param description: Set the fork description.
191 193 :type description: str
192 194 :param copy_permissions: Copy permissions from parent |repo|. The
193 195 default is False.
194 196 :type copy_permissions: bool
195 197 :param private: Make the fork private. The default is False.
196 198 :type private: bool
197 199 :param landing_rev: Set the landing revision. The default is tip.
198 200
199 201 Example output:
200 202
201 203 .. code-block:: bash
202 204
203 205 id : <id_for_response>
204 206 api_key : "<api_key>"
205 207 args: {
206 208 "repoid" : "<reponame or repo_id>",
207 209 "fork_name": "<forkname>",
208 210 "owner": "<username or user_id = Optional(=apiuser)>",
209 211 "description": "<description>",
210 212 "copy_permissions": "<bool>",
211 213 "private": "<bool>",
212 214 "landing_rev": "<landing_rev>"
213 215 }
214 216
215 217 Example error output:
216 218
217 219 .. code-block:: bash
218 220
219 221 id : <id_given_in_input>
220 222 result: {
221 223 "msg": "Created fork of `<reponame>` as `<forkname>`",
222 224 "success": true,
223 225 "task": "<celery task id or None if done sync>"
224 226 }
225 227 error: null
226 228
227 229
228 230 get_repo
229 231 --------
230 232
231 233 .. py:function:: get_repo(apiuser, repoid, cache=<Optional:True>)
232 234
233 235 Gets an existing repository by its name or repository_id.
234 236
235 237 The members section so the output returns users groups or users
236 238 associated with that repository.
237 239
238 240 This command can only be run using an |authtoken| with admin rights,
239 241 or users with at least read rights to the |repo|.
240 242
241 243 :param apiuser: This is filled automatically from the |authtoken|.
242 244 :type apiuser: AuthUser
243 245 :param repoid: The repository name or repository id.
244 246 :type repoid: str or int
245 247 :param cache: use the cached value for last changeset
246 248 :type: cache: Optional(bool)
247 249
248 250 Example output:
249 251
250 252 .. code-block:: bash
251 253
252 254 {
253 255 "error": null,
254 256 "id": <repo_id>,
255 257 "result": {
256 258 "clone_uri": null,
257 259 "created_on": "timestamp",
258 260 "description": "repo description",
259 261 "enable_downloads": false,
260 262 "enable_locking": false,
261 263 "enable_statistics": false,
262 264 "followers": [
263 265 {
264 266 "active": true,
265 267 "admin": false,
266 268 "api_key": "****************************************",
267 269 "api_keys": [
268 270 "****************************************"
269 271 ],
270 272 "email": "user@example.com",
271 273 "emails": [
272 274 "user@example.com"
273 275 ],
274 276 "extern_name": "rhodecode",
275 277 "extern_type": "rhodecode",
276 278 "firstname": "username",
277 279 "ip_addresses": [],
278 280 "language": null,
279 281 "last_login": "2015-09-16T17:16:35.854",
280 282 "lastname": "surname",
281 283 "user_id": <user_id>,
282 284 "username": "name"
283 285 }
284 286 ],
285 287 "fork_of": "parent-repo",
286 288 "landing_rev": [
287 289 "rev",
288 290 "tip"
289 291 ],
290 292 "last_changeset": {
291 293 "author": "User <user@example.com>",
292 294 "branch": "default",
293 295 "date": "timestamp",
294 296 "message": "last commit message",
295 297 "parents": [
296 298 {
297 299 "raw_id": "commit-id"
298 300 }
299 301 ],
300 302 "raw_id": "commit-id",
301 303 "revision": <revision number>,
302 304 "short_id": "short id"
303 305 },
304 306 "lock_reason": null,
305 307 "locked_by": null,
306 308 "locked_date": null,
307 309 "members": [
308 310 {
309 311 "name": "super-admin-name",
310 312 "origin": "super-admin",
311 313 "permission": "repository.admin",
312 314 "type": "user"
313 315 },
314 316 {
315 317 "name": "owner-name",
316 318 "origin": "owner",
317 319 "permission": "repository.admin",
318 320 "type": "user"
319 321 },
320 322 {
321 323 "name": "user-group-name",
322 324 "origin": "permission",
323 325 "permission": "repository.write",
324 326 "type": "user_group"
325 327 }
326 328 ],
327 329 "owner": "owner-name",
328 330 "permissions": [
329 331 {
330 332 "name": "super-admin-name",
331 333 "origin": "super-admin",
332 334 "permission": "repository.admin",
333 335 "type": "user"
334 336 },
335 337 {
336 338 "name": "owner-name",
337 339 "origin": "owner",
338 340 "permission": "repository.admin",
339 341 "type": "user"
340 342 },
341 343 {
342 344 "name": "user-group-name",
343 345 "origin": "permission",
344 346 "permission": "repository.write",
345 347 "type": "user_group"
346 348 }
347 349 ],
348 350 "private": true,
349 351 "repo_id": 676,
350 352 "repo_name": "user-group/repo-name",
351 353 "repo_type": "hg"
352 354 }
353 355 }
354 356
355 357
356 358 get_repo_changeset
357 359 ------------------
358 360
359 361 .. py:function:: get_repo_changeset(apiuser, repoid, revision, details=<Optional:'basic'>)
360 362
361 363 Returns information about a changeset.
362 364
363 365 Additionally parameters define the amount of details returned by
364 366 this function.
365 367
366 368 This command can only be run using an |authtoken| with admin rights,
367 369 or users with at least read rights to the |repo|.
368 370
369 371 :param apiuser: This is filled automatically from the |authtoken|.
370 372 :type apiuser: AuthUser
371 373 :param repoid: The repository name or repository id
372 374 :type repoid: str or int
373 375 :param revision: revision for which listing should be done
374 376 :type revision: str
375 377 :param details: details can be 'basic|extended|full' full gives diff
376 378 info details like the diff itself, and number of changed files etc.
377 379 :type details: Optional(str)
378 380
379 381
380 382 get_repo_changesets
381 383 -------------------
382 384
383 385 .. py:function:: get_repo_changesets(apiuser, repoid, start_rev, limit, details=<Optional:'basic'>)
384 386
385 387 Returns a set of commits limited by the number starting
386 388 from the `start_rev` option.
387 389
388 390 Additional parameters define the amount of details returned by this
389 391 function.
390 392
391 393 This command can only be run using an |authtoken| with admin rights,
392 394 or users with at least read rights to |repos|.
393 395
394 396 :param apiuser: This is filled automatically from the |authtoken|.
395 397 :type apiuser: AuthUser
396 398 :param repoid: The repository name or repository ID.
397 399 :type repoid: str or int
398 400 :param start_rev: The starting revision from where to get changesets.
399 401 :type start_rev: str
400 402 :param limit: Limit the number of commits to this amount
401 403 :type limit: str or int
402 404 :param details: Set the level of detail returned. Valid option are:
403 405 ``basic``, ``extended`` and ``full``.
404 406 :type details: Optional(str)
405 407
406 408 .. note::
407 409
408 410 Setting the parameter `details` to the value ``full`` is extensive
409 411 and returns details like the diff itself, and the number
410 412 of changed files.
411 413
412 414
413 415 get_repo_nodes
414 416 --------------
415 417
416 418 .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
417 419
418 420 Returns a list of nodes and children in a flat list for a given
419 421 path at given revision.
420 422
421 423 It's possible to specify ret_type to show only `files` or `dirs`.
422 424
423 425 This command can only be run using an |authtoken| with admin rights,
424 426 or users with at least read rights to |repos|.
425 427
426 428 :param apiuser: This is filled automatically from the |authtoken|.
427 429 :type apiuser: AuthUser
428 430 :param repoid: The repository name or repository ID.
429 431 :type repoid: str or int
430 432 :param revision: The revision for which listing should be done.
431 433 :type revision: str
432 434 :param root_path: The path from which to start displaying.
433 435 :type root_path: str
434 436 :param ret_type: Set the return type. Valid options are
435 437 ``all`` (default), ``files`` and ``dirs``.
436 438 :type ret_type: Optional(str)
437 439 :param details: Returns extended information about nodes, such as
438 440 md5, binary, and or content. The valid options are ``basic`` and
439 441 ``full``.
440 442 :type details: Optional(str)
441 443 :param max_file_bytes: Only return file content under this file size bytes
442 444 :type details: Optional(int)
443 445
444 446 Example output:
445 447
446 448 .. code-block:: bash
447 449
448 450 id : <id_given_in_input>
449 451 result: [
450 452 {
451 453 "name" : "<name>"
452 454 "type" : "<type>",
453 455 "binary": "<true|false>" (only in extended mode)
454 456 "md5" : "<md5 of file content>" (only in extended mode)
455 457 },
456 458 ...
457 459 ]
458 460 error: null
459 461
460 462
461 463 get_repo_refs
462 464 -------------
463 465
464 466 .. py:function:: get_repo_refs(apiuser, repoid)
465 467
466 468 Returns a dictionary of current references. It returns
467 469 bookmarks, branches, closed_branches, and tags for given repository
468 470
469 471 It's possible to specify ret_type to show only `files` or `dirs`.
470 472
471 473 This command can only be run using an |authtoken| with admin rights,
472 474 or users with at least read rights to |repos|.
473 475
474 476 :param apiuser: This is filled automatically from the |authtoken|.
475 477 :type apiuser: AuthUser
476 478 :param repoid: The repository name or repository ID.
477 479 :type repoid: str or int
478 480
479 481 Example output:
480 482
481 483 .. code-block:: bash
482 484
483 485 id : <id_given_in_input>
484 486 "result": {
485 487 "bookmarks": {
486 488 "dev": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
487 489 "master": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
488 490 },
489 491 "branches": {
490 492 "default": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
491 493 "stable": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
492 494 },
493 495 "branches_closed": {},
494 496 "tags": {
495 497 "tip": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
496 498 "v4.4.0": "1232313f9e6adac5ce5399c2a891dc1e72b79022",
497 499 "v4.4.1": "cbb9f1d329ae5768379cdec55a62ebdd546c4e27",
498 500 "v4.4.2": "24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17",
499 501 }
500 502 }
501 503 error: null
502 504
503 505
504 506 get_repo_settings
505 507 -----------------
506 508
507 509 .. py:function:: get_repo_settings(apiuser, repoid, key=<Optional:None>)
508 510
509 511 Returns all settings for a repository. If key is given it only returns the
510 512 setting identified by the key or null.
511 513
512 514 :param apiuser: This is filled automatically from the |authtoken|.
513 515 :type apiuser: AuthUser
514 516 :param repoid: The repository name or repository id.
515 517 :type repoid: str or int
516 518 :param key: Key of the setting to return.
517 519 :type: key: Optional(str)
518 520
519 521 Example output:
520 522
521 523 .. code-block:: bash
522 524
523 525 {
524 526 "error": null,
525 527 "id": 237,
526 528 "result": {
527 529 "extensions_largefiles": true,
528 530 "hooks_changegroup_push_logger": true,
529 531 "hooks_changegroup_repo_size": false,
530 532 "hooks_outgoing_pull_logger": true,
531 533 "phases_publish": "True",
532 534 "rhodecode_hg_use_rebase_for_merging": true,
533 535 "rhodecode_pr_merge_enabled": true,
534 536 "rhodecode_use_outdated_comments": true
535 537 }
536 538 }
537 539
538 540
539 541 get_repos
540 542 ---------
541 543
542 .. py:function:: get_repos(apiuser)
544 .. py:function:: get_repos(apiuser, root=<Optional:None>, traverse=<Optional:True>)
543 545
544 546 Lists all existing repositories.
545 547
546 548 This command can only be run using an |authtoken| with admin rights,
547 549 or users with at least read rights to |repos|.
548 550
549 551 :param apiuser: This is filled automatically from the |authtoken|.
550 552 :type apiuser: AuthUser
553 :param root: specify root repository group to fetch repositories.
554 filters the returned repositories to be members of given root group.
555 :type root: Optional(None)
556 :param traverse: traverse given root into subrepositories. With this flag
557 set to False, it will only return top-level repositories from `root`.
558 if root is empty it will return just top-level repositories.
559 :type traverse: Optional(True)
560
551 561
552 562 Example output:
553 563
554 564 .. code-block:: bash
555 565
556 566 id : <id_given_in_input>
557 567 result: [
558 568 {
559 569 "repo_id" : "<repo_id>",
560 570 "repo_name" : "<reponame>"
561 571 "repo_type" : "<repo_type>",
562 572 "clone_uri" : "<clone_uri>",
563 573 "private": : "<bool>",
564 574 "created_on" : "<datetimecreated>",
565 575 "description" : "<description>",
566 576 "landing_rev": "<landing_rev>",
567 577 "owner": "<repo_owner>",
568 578 "fork_of": "<name_of_fork_parent>",
569 579 "enable_downloads": "<bool>",
570 580 "enable_locking": "<bool>",
571 581 "enable_statistics": "<bool>",
572 582 },
573 583 ...
574 584 ]
575 585 error: null
576 586
577 587
578 588 grant_user_group_permission
579 589 ---------------------------
580 590
581 591 .. py:function:: grant_user_group_permission(apiuser, repoid, usergroupid, perm)
582 592
583 593 Grant permission for a user group on the specified repository,
584 594 or update existing permissions.
585 595
586 596 This command can only be run using an |authtoken| with admin
587 597 permissions on the |repo|.
588 598
589 599 :param apiuser: This is filled automatically from the |authtoken|.
590 600 :type apiuser: AuthUser
591 601 :param repoid: Set the repository name or repository ID.
592 602 :type repoid: str or int
593 603 :param usergroupid: Specify the ID of the user group.
594 604 :type usergroupid: str or int
595 605 :param perm: Set the user group permissions using the following
596 606 format: (repository.(none|read|write|admin))
597 607 :type perm: str
598 608
599 609 Example output:
600 610
601 611 .. code-block:: bash
602 612
603 613 id : <id_given_in_input>
604 614 result : {
605 615 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
606 616 "success": true
607 617
608 618 }
609 619 error : null
610 620
611 621 Example error output:
612 622
613 623 .. code-block:: bash
614 624
615 625 id : <id_given_in_input>
616 626 result : null
617 627 error : {
618 628 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
619 629 }
620 630
621 631
622 632 grant_user_permission
623 633 ---------------------
624 634
625 635 .. py:function:: grant_user_permission(apiuser, repoid, userid, perm)
626 636
627 637 Grant permissions for the specified user on the given repository,
628 638 or update existing permissions if found.
629 639
630 640 This command can only be run using an |authtoken| with admin
631 641 permissions on the |repo|.
632 642
633 643 :param apiuser: This is filled automatically from the |authtoken|.
634 644 :type apiuser: AuthUser
635 645 :param repoid: Set the repository name or repository ID.
636 646 :type repoid: str or int
637 647 :param userid: Set the user name.
638 648 :type userid: str
639 649 :param perm: Set the user permissions, using the following format
640 650 ``(repository.(none|read|write|admin))``
641 651 :type perm: str
642 652
643 653 Example output:
644 654
645 655 .. code-block:: bash
646 656
647 657 id : <id_given_in_input>
648 658 result: {
649 659 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
650 660 "success": true
651 661 }
652 662 error: null
653 663
654 664
655 665 invalidate_cache
656 666 ----------------
657 667
658 668 .. py:function:: invalidate_cache(apiuser, repoid, delete_keys=<Optional:False>)
659 669
660 670 Invalidates the cache for the specified repository.
661 671
662 672 This command can only be run using an |authtoken| with admin rights to
663 673 the specified repository.
664 674
665 675 This command takes the following options:
666 676
667 677 :param apiuser: This is filled automatically from |authtoken|.
668 678 :type apiuser: AuthUser
669 679 :param repoid: Sets the repository name or repository ID.
670 680 :type repoid: str or int
671 681 :param delete_keys: This deletes the invalidated keys instead of
672 682 just flagging them.
673 683 :type delete_keys: Optional(``True`` | ``False``)
674 684
675 685 Example output:
676 686
677 687 .. code-block:: bash
678 688
679 689 id : <id_given_in_input>
680 690 result : {
681 691 'msg': Cache for repository `<repository name>` was invalidated,
682 692 'repository': <repository name>
683 693 }
684 694 error : null
685 695
686 696 Example error output:
687 697
688 698 .. code-block:: bash
689 699
690 700 id : <id_given_in_input>
691 701 result : null
692 702 error : {
693 703 'Error occurred during cache invalidation action'
694 704 }
695 705
696 706
697 707 lock
698 708 ----
699 709
700 710 .. py:function:: lock(apiuser, repoid, locked=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
701 711
702 712 Sets the lock state of the specified |repo| by the given user.
703 713 From more information, see :ref:`repo-locking`.
704 714
705 715 * If the ``userid`` option is not set, the repository is locked to the
706 716 user who called the method.
707 717 * If the ``locked`` parameter is not set, the current lock state of the
708 718 repository is displayed.
709 719
710 720 This command can only be run using an |authtoken| with admin rights to
711 721 the specified repository.
712 722
713 723 This command takes the following options:
714 724
715 725 :param apiuser: This is filled automatically from the |authtoken|.
716 726 :type apiuser: AuthUser
717 727 :param repoid: Sets the repository name or repository ID.
718 728 :type repoid: str or int
719 729 :param locked: Sets the lock state.
720 730 :type locked: Optional(``True`` | ``False``)
721 731 :param userid: Set the repository lock to this user.
722 732 :type userid: Optional(str or int)
723 733
724 734 Example error output:
725 735
726 736 .. code-block:: bash
727 737
728 738 id : <id_given_in_input>
729 739 result : {
730 740 'repo': '<reponame>',
731 741 'locked': <bool: lock state>,
732 742 'locked_since': <int: lock timestamp>,
733 743 'locked_by': <username of person who made the lock>,
734 744 'lock_reason': <str: reason for locking>,
735 745 'lock_state_changed': <bool: True if lock state has been changed in this request>,
736 746 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
737 747 or
738 748 'msg': 'Repo `<repository name>` not locked.'
739 749 or
740 750 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
741 751 }
742 752 error : null
743 753
744 754 Example error output:
745 755
746 756 .. code-block:: bash
747 757
748 758 id : <id_given_in_input>
749 759 result : null
750 760 error : {
751 761 'Error occurred locking repository `<reponame>`'
752 762 }
753 763
754 764
755 765 pull
756 766 ----
757 767
758 768 .. py:function:: pull(apiuser, repoid)
759 769
760 770 Triggers a pull on the given repository from a remote location. You
761 771 can use this to keep remote repositories up-to-date.
762 772
763 773 This command can only be run using an |authtoken| with admin
764 774 rights to the specified repository. For more information,
765 775 see :ref:`config-token-ref`.
766 776
767 777 This command takes the following options:
768 778
769 779 :param apiuser: This is filled automatically from the |authtoken|.
770 780 :type apiuser: AuthUser
771 781 :param repoid: The repository name or repository ID.
772 782 :type repoid: str or int
773 783
774 784 Example output:
775 785
776 786 .. code-block:: bash
777 787
778 788 id : <id_given_in_input>
779 789 result : {
780 790 "msg": "Pulled from `<repository name>`"
781 791 "repository": "<repository name>"
782 792 }
783 793 error : null
784 794
785 795 Example error output:
786 796
787 797 .. code-block:: bash
788 798
789 799 id : <id_given_in_input>
790 800 result : null
791 801 error : {
792 802 "Unable to pull changes from `<reponame>`"
793 803 }
794 804
795 805
796 806 remove_field_from_repo
797 807 ----------------------
798 808
799 809 .. py:function:: remove_field_from_repo(apiuser, repoid, key)
800 810
801 811 Removes an extra field from a repository.
802 812
803 813 This command can only be run using an |authtoken| with at least
804 814 write permissions to the |repo|.
805 815
806 816 :param apiuser: This is filled automatically from the |authtoken|.
807 817 :type apiuser: AuthUser
808 818 :param repoid: Set the repository name or repository ID.
809 819 :type repoid: str or int
810 820 :param key: Set the unique field key for this repository.
811 821 :type key: str
812 822
813 823
814 824 revoke_user_group_permission
815 825 ----------------------------
816 826
817 827 .. py:function:: revoke_user_group_permission(apiuser, repoid, usergroupid)
818 828
819 829 Revoke the permissions of a user group on a given repository.
820 830
821 831 This command can only be run using an |authtoken| with admin
822 832 permissions on the |repo|.
823 833
824 834 :param apiuser: This is filled automatically from the |authtoken|.
825 835 :type apiuser: AuthUser
826 836 :param repoid: Set the repository name or repository ID.
827 837 :type repoid: str or int
828 838 :param usergroupid: Specify the user group ID.
829 839 :type usergroupid: str or int
830 840
831 841 Example output:
832 842
833 843 .. code-block:: bash
834 844
835 845 id : <id_given_in_input>
836 846 result: {
837 847 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
838 848 "success": true
839 849 }
840 850 error: null
841 851
842 852
843 853 revoke_user_permission
844 854 ----------------------
845 855
846 856 .. py:function:: revoke_user_permission(apiuser, repoid, userid)
847 857
848 858 Revoke permission for a user on the specified repository.
849 859
850 860 This command can only be run using an |authtoken| with admin
851 861 permissions on the |repo|.
852 862
853 863 :param apiuser: This is filled automatically from the |authtoken|.
854 864 :type apiuser: AuthUser
855 865 :param repoid: Set the repository name or repository ID.
856 866 :type repoid: str or int
857 867 :param userid: Set the user name of revoked user.
858 868 :type userid: str or int
859 869
860 870 Example error output:
861 871
862 872 .. code-block:: bash
863 873
864 874 id : <id_given_in_input>
865 875 result: {
866 876 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
867 877 "success": true
868 878 }
869 879 error: null
870 880
871 881
872 882 set_repo_settings
873 883 -----------------
874 884
875 885 .. py:function:: set_repo_settings(apiuser, repoid, settings)
876 886
877 887 Update repository settings. Returns true on success.
878 888
879 889 :param apiuser: This is filled automatically from the |authtoken|.
880 890 :type apiuser: AuthUser
881 891 :param repoid: The repository name or repository id.
882 892 :type repoid: str or int
883 893 :param settings: The new settings for the repository.
884 894 :type: settings: dict
885 895
886 896 Example output:
887 897
888 898 .. code-block:: bash
889 899
890 900 {
891 901 "error": null,
892 902 "id": 237,
893 903 "result": true
894 904 }
895 905
896 906
897 907 strip
898 908 -----
899 909
900 910 .. py:function:: strip(apiuser, repoid, revision, branch)
901 911
902 912 Strips the given revision from the specified repository.
903 913
904 914 * This will remove the revision and all of its decendants.
905 915
906 916 This command can only be run using an |authtoken| with admin rights to
907 917 the specified repository.
908 918
909 919 This command takes the following options:
910 920
911 921 :param apiuser: This is filled automatically from the |authtoken|.
912 922 :type apiuser: AuthUser
913 923 :param repoid: The repository name or repository ID.
914 924 :type repoid: str or int
915 925 :param revision: The revision you wish to strip.
916 926 :type revision: str
917 927 :param branch: The branch from which to strip the revision.
918 928 :type branch: str
919 929
920 930 Example output:
921 931
922 932 .. code-block:: bash
923 933
924 934 id : <id_given_in_input>
925 935 result : {
926 936 "msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
927 937 "repository": "<repository name>"
928 938 }
929 939 error : null
930 940
931 941 Example error output:
932 942
933 943 .. code-block:: bash
934 944
935 945 id : <id_given_in_input>
936 946 result : null
937 947 error : {
938 948 "Unable to strip commit <commit_hash> from repo `<repository name>`"
939 949 }
940 950
941 951
942 952 update_repo
943 953 -----------
944 954
945 955 .. py:function:: update_repo(apiuser, repoid, repo_name=<Optional:None>, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, fork_of=<Optional:None>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, fields=<Optional:''>)
946 956
947 957 Updates a repository with the given information.
948 958
949 959 This command can only be run using an |authtoken| with at least
950 960 admin permissions to the |repo|.
951 961
952 962 * If the repository name contains "/", repository will be updated
953 963 accordingly with a repository group or nested repository groups
954 964
955 965 For example repoid=repo-test name="foo/bar/repo-test" will update |repo|
956 966 called "repo-test" and place it inside group "foo/bar".
957 967 You have to have permissions to access and write to the last repository
958 968 group ("bar" in this example)
959 969
960 970 :param apiuser: This is filled automatically from the |authtoken|.
961 971 :type apiuser: AuthUser
962 972 :param repoid: repository name or repository ID.
963 973 :type repoid: str or int
964 974 :param repo_name: Update the |repo| name, including the
965 975 repository group it's in.
966 976 :type repo_name: str
967 977 :param owner: Set the |repo| owner.
968 978 :type owner: str
969 979 :param fork_of: Set the |repo| as fork of another |repo|.
970 980 :type fork_of: str
971 981 :param description: Update the |repo| description.
972 982 :type description: str
973 983 :param private: Set the |repo| as private. (True | False)
974 984 :type private: bool
975 985 :param clone_uri: Update the |repo| clone URI.
976 986 :type clone_uri: str
977 987 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
978 988 :type landing_rev: str
979 989 :param enable_statistics: Enable statistics on the |repo|, (True | False).
980 990 :type enable_statistics: bool
981 991 :param enable_locking: Enable |repo| locking.
982 992 :type enable_locking: bool
983 993 :param enable_downloads: Enable downloads from the |repo|, (True | False).
984 994 :type enable_downloads: bool
985 995 :param fields: Add extra fields to the |repo|. Use the following
986 996 example format: ``field_key=field_val,field_key2=fieldval2``.
987 997 Escape ', ' with \,
988 998 :type fields: str
989 999
990 1000
@@ -1,115 +1,158 b''
1 1 .. _server-methods-ref:
2 2
3 3 server methods
4 4 ==============
5 5
6 cleanup_sessions
7 ----------------
8
9 .. py:function:: cleanup_sessions(apiuser, older_then=<Optional:60>)
10
11 Triggers a session cleanup action.
12
13 If the ``older_then`` option is set, only sessions that hasn't been
14 accessed in the given number of days will be removed.
15
16 This command can only be run using an |authtoken| with admin rights to
17 the specified repository.
18
19 This command takes the following options:
20
21 :param apiuser: This is filled automatically from the |authtoken|.
22 :type apiuser: AuthUser
23 :param older_then: Deletes session that hasn't been accessed
24 in given number of days.
25 :type older_then: Optional(int)
26
27 Example output:
28
29 .. code-block:: bash
30
31 id : <id_given_in_input>
32 result: {
33 "backend": "<type of backend>",
34 "sessions_removed": <number_of_removed_sessions>
35 }
36 error : null
37
38 Example error output:
39
40 .. code-block:: bash
41
42 id : <id_given_in_input>
43 result : null
44 error : {
45 'Error occurred during session cleanup'
46 }
47
48
6 49 get_ip
7 50 ------
8 51
9 52 .. py:function:: get_ip(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
10 53
11 54 Displays the IP Address as seen from the |RCE| server.
12 55
13 56 * This command displays the IP Address, as well as all the defined IP
14 57 addresses for the specified user. If the ``userid`` is not set, the
15 58 data returned is for the user calling the method.
16 59
17 60 This command can only be run using an |authtoken| with admin rights to
18 61 the specified repository.
19 62
20 63 This command takes the following options:
21 64
22 65 :param apiuser: This is filled automatically from |authtoken|.
23 66 :type apiuser: AuthUser
24 67 :param userid: Sets the userid for which associated IP Address data
25 68 is returned.
26 69 :type userid: Optional(str or int)
27 70
28 71 Example output:
29 72
30 73 .. code-block:: bash
31 74
32 75 id : <id_given_in_input>
33 76 result : {
34 77 "server_ip_addr": "<ip_from_clien>",
35 78 "user_ips": [
36 79 {
37 80 "ip_addr": "<ip_with_mask>",
38 81 "ip_range": ["<start_ip>", "<end_ip>"],
39 82 },
40 83 ...
41 84 ]
42 85 }
43 86
44 87
45 88 get_server_info
46 89 ---------------
47 90
48 91 .. py:function:: get_server_info(apiuser)
49 92
50 93 Returns the |RCE| server information.
51 94
52 95 This includes the running version of |RCE| and all installed
53 96 packages. This command takes the following options:
54 97
55 98 :param apiuser: This is filled automatically from the |authtoken|.
56 99 :type apiuser: AuthUser
57 100
58 101 Example output:
59 102
60 103 .. code-block:: bash
61 104
62 105 id : <id_given_in_input>
63 106 result : {
64 107 'modules': [<module name>,...]
65 108 'py_version': <python version>,
66 109 'platform': <platform type>,
67 110 'rhodecode_version': <rhodecode version>
68 111 }
69 112 error : null
70 113
71 114
72 115 rescan_repos
73 116 ------------
74 117
75 118 .. py:function:: rescan_repos(apiuser, remove_obsolete=<Optional:False>)
76 119
77 120 Triggers a rescan of the specified repositories.
78 121
79 122 * If the ``remove_obsolete`` option is set, it also deletes repositories
80 123 that are found in the database but not on the file system, so called
81 124 "clean zombies".
82 125
83 126 This command can only be run using an |authtoken| with admin rights to
84 127 the specified repository.
85 128
86 129 This command takes the following options:
87 130
88 131 :param apiuser: This is filled automatically from the |authtoken|.
89 132 :type apiuser: AuthUser
90 133 :param remove_obsolete: Deletes repositories from the database that
91 134 are not found on the filesystem.
92 135 :type remove_obsolete: Optional(``True`` | ``False``)
93 136
94 137 Example output:
95 138
96 139 .. code-block:: bash
97 140
98 141 id : <id_given_in_input>
99 142 result : {
100 143 'added': [<added repository name>,...]
101 144 'removed': [<removed repository name>,...]
102 145 }
103 146 error : null
104 147
105 148 Example error output:
106 149
107 150 .. code-block:: bash
108 151
109 152 id : <id_given_in_input>
110 153 result : null
111 154 error : {
112 155 'Error occurred during rescan repositories action'
113 156 }
114 157
115 158
@@ -1,160 +1,186 b''
1 1 .. _dev-setup:
2 2
3 3 ===================
4 4 Development setup
5 5 ===================
6 6
7 7
8 8 RhodeCode Enterprise runs inside a Nix managed environment. This ensures build
9 9 environment dependencies are correctly declared and installed during setup.
10 10 It also enables atomic upgrades, rollbacks, and multiple instances of RhodeCode
11 11 Enterprise running with isolation.
12 12
13 13 To set up RhodeCode Enterprise inside the Nix environment, use the following steps:
14 14
15 15
16 16
17 17 Setup Nix Package Manager
18 18 -------------------------
19 19
20 20 To install the Nix Package Manager, please run::
21 21
22 22 $ curl https://nixos.org/nix/install | sh
23 23
24 24 or go to https://nixos.org/nix/ and follow the installation instructions.
25 25 Once this is correctly set up on your system, you should be able to use the
26 26 following commands:
27 27
28 28 * `nix-env`
29 29
30 30 * `nix-shell`
31 31
32 32
33 33 .. tip::
34 34
35 35 Update your channels frequently by running ``nix-channel --upgrade``.
36 36
37 37
38 38 Switch nix to the latest STABLE channel
39 39 ---------------------------------------
40 40
41 41 run::
42 42
43 43 nix-channel --add https://nixos.org/channels/nixos-16.03 nixpkgs
44 44
45 45 Followed by::
46 46
47 47 nix-channel --update
48 48
49 49
50 Install required binaries
51 -------------------------
52
53 We need some handy tools first.
54
55 run::
56
57 nix-env -i nix-prefetch-hg
58 nix-env -i nix-prefetch-git
59
60
50 61 Clone the required repositories
51 62 -------------------------------
52 63
53 64 After Nix is set up, clone the RhodeCode Enterprise Community Edition and
54 65 RhodeCode VCSServer repositories into the same directory.
55 66 To do this, use the following example::
56 67
57 68 mkdir rhodecode-develop && cd rhodecode-develop
58 69 hg clone https://code.rhodecode.com/rhodecode-enterprise-ce
59 70 hg clone https://code.rhodecode.com/rhodecode-vcsserver
60 71
61 72 .. note::
62 73
63 74 If you cannot clone the repository, please request read permissions
64 75 via support@rhodecode.com
65 76
66 77
78 Install some required libraries
79 -------------------------------
80
81 There are some required drivers that we need to install to test RhodeCode
82 under different types of databases. For example in Ubuntu we need to install
83 the following.
84
85 required libraries::
86
87 sudo apt-get install libapr1-dev libaprutil1-dev
88 sudo apt-get install libsvn-dev
89 sudo apt-get install mysql-server libmysqlclient-dev
90 sudo apt-get install postgresql postgresql-contrib libpq-dev
91 sudo apt-get install libcurl4-openssl-dev
92
67 93
68 94 Enter the Development Shell
69 95 ---------------------------
70 96
71 97 The final step is to start the development shell. To do this, run the
72 98 following command from inside the cloned repository::
73 99
74 100 cd ~/rhodecode-enterprise-ce
75 101 nix-shell
76 102
77 103 .. note::
78 104
79 105 On the first run, this will take a while to download and optionally compile
80 106 a few things. The following runs will be faster. The development shell works
81 107 fine on both MacOS and Linux platforms.
82 108
83 109
84 110
85 111 Creating a Development Configuration
86 112 ------------------------------------
87 113
88 114 To create a development environment for RhodeCode Enterprise,
89 115 use the following steps:
90 116
91 117 1. Create a copy of `~/rhodecode-enterprise-ce/configs/development.ini`
92 118 2. Adjust the configuration settings to your needs
93 119
94 120 .. note::
95 121
96 122 It is recommended to use the name `dev.ini`.
97 123
98 124
99 125 Setup the Development Database
100 126 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
101 127
102 128 To create a development database, use the following example. This is a one
103 129 time operation::
104 130
105 131 paster setup-rhodecode dev.ini \
106 132 --user=admin --password=secret \
107 133 --email=admin@example.com \
108 134 --repos=~/my_dev_repos
109 135
110 136
111 137 Compile CSS and JavaScript
112 138 ^^^^^^^^^^^^^^^^^^^^^^^^^^
113 139
114 140 To use the application's frontend and prepare it for production deployment,
115 141 you will need to compile the CSS and JavaScript with Grunt.
116 142 This is easily done from within the nix-shell using the following command::
117 143
118 144 grunt
119 145
120 146 When developing new features you will need to recompile following any
121 147 changes made to the CSS or JavaScript files when developing the code::
122 148
123 149 grunt watch
124 150
125 151 This prepares the development (with comments/whitespace) versions of files.
126 152
127 153 Start the Development Server
128 154 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
129 155
130 156 From the rhodecode-vcsserver directory, start the development server in another
131 157 nix-shell, using the following command::
132 158
133 159 pserve configs/development.ini http_port=9900
134 160
135 161 In the adjacent nix-shell which you created for your development server, you may
136 162 now start CE with the following command::
137 163
138 164
139 165 rcserver dev.ini
140 166
141 167 .. note::
142 168
143 169 To automatically refresh - and recompile the frontend assets - when changes
144 170 are made in the source code, you can use the option `--reload`.
145 171
146 172
147 173 Run the Environment Tests
148 174 ^^^^^^^^^^^^^^^^^^^^^^^^^
149 175
150 176 Please make sure that the tests are passing to verify that your environment is
151 177 set up correctly. RhodeCode uses py.test to run tests.
152 178 While your instance is running, start a new nix-shell and simply run
153 179 ``make test`` to run the basic test suite.
154 180
155 181
156 182 Need Help?
157 183 ^^^^^^^^^^
158 184
159 185 Join us on Slack via https://rhodecode.com/join or post questions in our
160 186 Community Portal at https://community.rhodecode.com
@@ -1,92 +1,93 b''
1 1 .. _rhodecode-release-notes-ref:
2 2
3 3 Release Notes
4 4 =============
5 5
6 6 |RCE| 4.x Versions
7 7 ------------------
8 8
9 9 .. toctree::
10 10 :maxdepth: 1
11 11
12 release-notes-4.6.0.rst
12 13 release-notes-4.5.2.rst
13 14 release-notes-4.5.1.rst
14 15 release-notes-4.5.0.rst
15 16 release-notes-4.4.2.rst
16 17 release-notes-4.4.1.rst
17 18 release-notes-4.4.0.rst
18 19 release-notes-4.3.1.rst
19 20 release-notes-4.3.0.rst
20 21 release-notes-4.2.1.rst
21 22 release-notes-4.2.0.rst
22 23 release-notes-4.1.2.rst
23 24 release-notes-4.1.1.rst
24 25 release-notes-4.1.0.rst
25 26 release-notes-4.0.1.rst
26 27 release-notes-4.0.0.rst
27 28
28 29 |RCE| 3.x Versions
29 30 ------------------
30 31
31 32 .. toctree::
32 33 :maxdepth: 1
33 34
34 35 release-notes-3.8.4.rst
35 36 release-notes-3.8.3.rst
36 37 release-notes-3.8.2.rst
37 38 release-notes-3.8.1.rst
38 39 release-notes-3.8.0.rst
39 40 release-notes-3.7.1.rst
40 41 release-notes-3.7.0.rst
41 42 release-notes-3.6.1.rst
42 43 release-notes-3.6.0.rst
43 44 release-notes-3.5.2.rst
44 45 release-notes-3.5.1.rst
45 46 release-notes-3.5.0.rst
46 47 release-notes-3.4.1.rst
47 48 release-notes-3.4.0.rst
48 49 release-notes-3.3.4.rst
49 50 release-notes-3.3.3.rst
50 51 release-notes-3.3.2.rst
51 52 release-notes-3.3.1.rst
52 53 release-notes-3.3.0.rst
53 54 release-notes-3.2.3.rst
54 55 release-notes-3.2.2.rst
55 56 release-notes-3.2.1.rst
56 57 release-notes-3.2.0.rst
57 58 release-notes-3.1.1.rst
58 59 release-notes-3.1.0.rst
59 60 release-notes-3.0.2.rst
60 61 release-notes-3.0.1.rst
61 62 release-notes-3.0.0.rst
62 63
63 64 |RCE| 2.x Versions
64 65 ------------------
65 66
66 67 .. toctree::
67 68 :maxdepth: 1
68 69
69 70 release-notes-2.2.8.rst
70 71 release-notes-2.2.7.rst
71 72 release-notes-2.2.6.rst
72 73 release-notes-2.2.5.rst
73 74 release-notes-2.2.4.rst
74 75 release-notes-2.2.3.rst
75 76 release-notes-2.2.2.rst
76 77 release-notes-2.2.1.rst
77 78 release-notes-2.2.0.rst
78 79 release-notes-2.1.0.rst
79 80 release-notes-2.0.2.rst
80 81 release-notes-2.0.1.rst
81 82 release-notes-2.0.0.rst
82 83
83 84 |RCE| 1.x Versions
84 85 ------------------
85 86
86 87 .. toctree::
87 88 :maxdepth: 1
88 89
89 90 release-notes-1.7.2.rst
90 91 release-notes-1.7.1.rst
91 92 release-notes-1.7.0.rst
92 93 release-notes-1.6.0.rst
@@ -1,190 +1,191 b''
1 1 {
2 2 "dirs": {
3 3 "css": {
4 4 "src":"rhodecode/public/css",
5 5 "dest":"rhodecode/public/css"
6 6 },
7 7 "js": {
8 8 "src": "rhodecode/public/js/src",
9 9 "dest": "rhodecode/public/js",
10 10 "bower": "bower_components",
11 11 "node_modules": "node_modules"
12 12 }
13 13 },
14 14 "copy": {
15 15 "main": {
16 16 "expand": true,
17 17 "cwd": "bower_components",
18 18 "src": "webcomponentsjs/webcomponents-lite.js",
19 19 "dest": "<%= dirs.js.dest %>/vendors"
20 20 }
21 21 },
22 22 "concat": {
23 23 "polymercss": {
24 24 "src": [
25 25 "<%= dirs.js.src %>/components/root-styles-prefix.html",
26 26 "<%= dirs.css.src %>/style-polymer.css",
27 27 "<%= dirs.js.src %>/components/root-styles-suffix.html"
28 28 ],
29 29 "dest": "<%= dirs.js.dest %>/src/components/root-styles.gen.html",
30 30 "nonull": true
31 31 },
32 32 "dist": {
33 33 "src": [
34 34 "<%= dirs.js.src %>/jquery-1.11.1.min.js",
35 35 "<%= dirs.js.src %>/logging.js",
36 36 "<%= dirs.js.src %>/bootstrap.js",
37 37 "<%= dirs.js.src %>/mousetrap.js",
38 38 "<%= dirs.js.src %>/moment.js",
39 39 "<%= dirs.js.node_modules %>/appenlight-client/appenlight-client.min.js",
40 40 "<%= dirs.js.node_modules %>/favico.js/favico-0.3.10.min.js",
41 41 "<%= dirs.js.src %>/i18n_utils.js",
42 42 "<%= dirs.js.src %>/deform.js",
43 43 "<%= dirs.js.src %>/plugins/jquery.pjax.js",
44 44 "<%= dirs.js.src %>/plugins/jquery.dataTables.js",
45 45 "<%= dirs.js.src %>/plugins/flavoured_checkbox.js",
46 46 "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js",
47 47 "<%= dirs.js.src %>/plugins/jquery.autocomplete.js",
48 48 "<%= dirs.js.src %>/plugins/jquery.debounce.js",
49 49 "<%= dirs.js.src %>/plugins/jquery.mark.js",
50 50 "<%= dirs.js.src %>/plugins/jquery.timeago.js",
51 51 "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js",
52 52 "<%= dirs.js.src %>/select2/select2.js",
53 53 "<%= dirs.js.src %>/codemirror/codemirror.js",
54 54 "<%= dirs.js.src %>/codemirror/codemirror_loadmode.js",
55 55 "<%= dirs.js.src %>/codemirror/codemirror_hint.js",
56 56 "<%= dirs.js.src %>/codemirror/codemirror_overlay.js",
57 57 "<%= dirs.js.src %>/codemirror/codemirror_placeholder.js",
58 58 "<%= dirs.js.dest %>/mode/meta.js",
59 59 "<%= dirs.js.dest %>/mode/meta_ext.js",
60 60 "<%= dirs.js.dest %>/rhodecode/i18n/select2/translations.js",
61 61 "<%= dirs.js.src %>/rhodecode/utils/array.js",
62 62 "<%= dirs.js.src %>/rhodecode/utils/string.js",
63 63 "<%= dirs.js.src %>/rhodecode/utils/pyroutes.js",
64 64 "<%= dirs.js.src %>/rhodecode/utils/ajax.js",
65 65 "<%= dirs.js.src %>/rhodecode/utils/autocomplete.js",
66 66 "<%= dirs.js.src %>/rhodecode/utils/colorgenerator.js",
67 67 "<%= dirs.js.src %>/rhodecode/utils/ie.js",
68 68 "<%= dirs.js.src %>/rhodecode/utils/os.js",
69 69 "<%= dirs.js.src %>/rhodecode/utils/topics.js",
70 70 "<%= dirs.js.src %>/rhodecode/init.js",
71 "<%= dirs.js.src %>/rhodecode/changelog.js",
71 72 "<%= dirs.js.src %>/rhodecode/codemirror.js",
72 73 "<%= dirs.js.src %>/rhodecode/comments.js",
73 74 "<%= dirs.js.src %>/rhodecode/constants.js",
74 75 "<%= dirs.js.src %>/rhodecode/files.js",
75 76 "<%= dirs.js.src %>/rhodecode/followers.js",
76 77 "<%= dirs.js.src %>/rhodecode/menus.js",
77 78 "<%= dirs.js.src %>/rhodecode/notifications.js",
78 79 "<%= dirs.js.src %>/rhodecode/permissions.js",
79 80 "<%= dirs.js.src %>/rhodecode/pjax.js",
80 81 "<%= dirs.js.src %>/rhodecode/pullrequests.js",
81 82 "<%= dirs.js.src %>/rhodecode/settings.js",
82 83 "<%= dirs.js.src %>/rhodecode/select2_widgets.js",
83 84 "<%= dirs.js.src %>/rhodecode/tooltips.js",
84 85 "<%= dirs.js.src %>/rhodecode/users.js",
85 86 "<%= dirs.js.src %>/rhodecode/appenlight.js",
86 87 "<%= dirs.js.src %>/rhodecode.js"
87 88 ],
88 89 "dest": "<%= dirs.js.dest %>/scripts.js",
89 90 "nonull": true
90 91 }
91 92 },
92 93 "crisper": {
93 94 "dist": {
94 95 "options": {
95 96 "cleanup": false,
96 97 "onlySplit": true
97 98 },
98 99 "src": "<%= dirs.js.dest %>/rhodecode-components.html",
99 100 "dest": "<%= dirs.js.dest %>/rhodecode-components.js"
100 101 }
101 102 },
102 103 "less": {
103 104 "development": {
104 105 "options": {
105 106 "compress": false,
106 107 "yuicompress": false,
107 108 "optimization": 0
108 109 },
109 110 "files": {
110 111 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
111 112 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less"
112 113 }
113 114 },
114 115 "production": {
115 116 "options": {
116 117 "compress": true,
117 118 "yuicompress": true,
118 119 "optimization": 2
119 120 },
120 121 "files": {
121 122 "<%= dirs.css.dest %>/style.css": "<%= dirs.css.src %>/main.less",
122 123 "<%= dirs.css.dest %>/style-polymer.css": "<%= dirs.css.src %>/polymer.less"
123 124 }
124 125 },
125 126 "components": {
126 127 "files": [
127 128 {
128 129 "cwd": "<%= dirs.js.src %>/components/",
129 130 "dest": "<%= dirs.js.src %>/components/",
130 131 "src": [
131 132 "**/*.less"
132 133 ],
133 134 "expand": true,
134 135 "ext": ".css"
135 136 }
136 137 ]
137 138 }
138 139 },
139 140 "watch": {
140 141 "less": {
141 142 "files": [
142 143 "<%= dirs.css.src %>/**/*.less",
143 144 "<%= dirs.js.src %>/components/**/*.less"
144 145 ],
145 146 "tasks": [
146 147 "less:development",
147 148 "less:components",
148 149 "concat:polymercss",
149 150 "vulcanize",
150 151 "crisper",
151 152 "concat:dist"
152 153 ]
153 154 },
154 155 "js": {
155 156 "files": [
156 157 "!<%= dirs.js.src %>/components/root-styles.gen.html",
157 158 "<%= dirs.js.src %>/**/*.js",
158 159 "<%= dirs.js.src %>/components/**/*.html"
159 160 ],
160 161 "tasks": [
161 162 "less:components",
162 163 "concat:polymercss",
163 164 "vulcanize",
164 165 "crisper",
165 166 "concat:dist"
166 167 ]
167 168 }
168 169 },
169 170 "jshint": {
170 171 "rhodecode": {
171 172 "src": "<%= dirs.js.src %>/rhodecode/**/*.js",
172 173 "options": {
173 174 "jshintrc": ".jshintrc"
174 175 }
175 176 }
176 177 },
177 178 "vulcanize": {
178 179 "default": {
179 180 "options": {
180 181 "abspath": "",
181 182 "inlineScripts": true,
182 183 "inlineCss": true,
183 184 "stripComments": true
184 185 },
185 186 "files": {
186 187 "<%= dirs.js.dest %>/rhodecode-components.html": "<%= dirs.js.src %>/components/shared-components.html"
187 188 }
188 189 }
189 190 }
190 191 }
@@ -1,286 +1,261 b''
1 1 # Overrides for the generated python-packages.nix
2 2 #
3 3 # This function is intended to be used as an extension to the generated file
4 4 # python-packages.nix. The main objective is to add needed dependencies of C
5 5 # libraries and tweak the build instructions where needed.
6 6
7 7 { pkgs, basePythonPackages }:
8 8
9 9 let
10 10 sed = "sed -i";
11 11 localLicenses = {
12 12 repoze = {
13 13 fullName = "Repoze License";
14 14 url = http://www.repoze.org/LICENSE.txt;
15 15 };
16 16 };
17 17
18 18 in
19 19
20 20 self: super: {
21 21
22 22 appenlight-client = super.appenlight-client.override (attrs: {
23 23 meta = {
24 24 license = [ pkgs.lib.licenses.bsdOriginal ];
25 25 };
26 26 });
27 27
28 28 future = super.future.override (attrs: {
29 29 meta = {
30 30 license = [ pkgs.lib.licenses.mit ];
31 31 };
32 32 });
33 33
34 34 gnureadline = super.gnureadline.override (attrs: {
35 35 buildInputs = attrs.buildInputs ++ [
36 36 pkgs.ncurses
37 37 ];
38 38 patchPhase = ''
39 39 substituteInPlace setup.py --replace "/bin/bash" "${pkgs.bash}/bin/bash"
40 40 '';
41 41 });
42 42
43 43 gunicorn = super.gunicorn.override (attrs: {
44 44 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
45 45 # johbo: futures is needed as long as we are on Python 2, otherwise
46 46 # gunicorn explodes if used with multiple threads per worker.
47 47 self.futures
48 48 ];
49 49 });
50 50
51 51 ipython = super.ipython.override (attrs: {
52 52 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
53 53 self.gnureadline
54 54 ];
55 55 });
56 56
57 57 kombu = super.kombu.override (attrs: {
58 58 # The current version of kombu needs some patching to work with the
59 59 # other libs. Should be removed once we update celery and kombu.
60 60 patches = [
61 61 ./patch-kombu-py-2-7-11.diff
62 62 ./patch-kombu-msgpack.diff
63 63 ];
64 64 });
65 65
66 66 lxml = super.lxml.override (attrs: {
67 67 # johbo: On 16.09 we need this to compile on darwin, otherwise compilation
68 68 # fails on Darwin.
69 69 hardeningDisable = if pkgs.stdenv.isDarwin then [ "format" ] else null;
70 70 buildInputs = with self; [
71 71 pkgs.libxml2
72 72 pkgs.libxslt
73 73 ];
74 74 });
75 75
76 76 MySQL-python = super.MySQL-python.override (attrs: {
77 77 buildInputs = attrs.buildInputs ++ [
78 78 pkgs.openssl
79 79 ];
80 80 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
81 81 pkgs.mysql.lib
82 82 pkgs.zlib
83 83 ];
84 84 });
85 85
86 86 psutil = super.psutil.override (attrs: {
87 87 buildInputs = attrs.buildInputs ++
88 88 pkgs.lib.optional pkgs.stdenv.isDarwin pkgs.darwin.IOKit;
89 89 });
90 90
91 91 psycopg2 = super.psycopg2.override (attrs: {
92 92 buildInputs = attrs.buildInputs ++
93 93 pkgs.lib.optional pkgs.stdenv.isDarwin pkgs.openssl;
94 94 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
95 95 pkgs.postgresql
96 96 ];
97 97 meta = {
98 98 license = pkgs.lib.licenses.lgpl3Plus;
99 99 };
100 100 });
101 101
102 102 py-gfm = super.py-gfm.override {
103 src = pkgs.fetchgit {
104 url = "https://code.rhodecode.com/upstream/py-gfm";
105 rev = "0d66a19bc16e3d49de273c0f797d4e4781e8c0f2";
106 sha256 = "0ryp74jyihd3ckszq31bml5jr3bciimhfp7va7kw6ld92930ksv3";
107 };
103 name = "py-gfm-0.1.3.rhodecode-upstream1";
108 104 };
109 105
110 106 pycurl = super.pycurl.override (attrs: {
111 107 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
112 108 pkgs.curl
113 109 pkgs.openssl
114 110 ];
115 111 preConfigure = ''
116 112 substituteInPlace setup.py --replace '--static-libs' '--libs'
117 113 export PYCURL_SSL_LIBRARY=openssl
118 114 '';
119 115 meta = {
120 116 # TODO: It is LGPL and MIT
121 117 license = pkgs.lib.licenses.mit;
122 118 };
123 119 });
124 120
125 121 Pylons = super.Pylons.override (attrs: {
126 name = "Pylons-1.0.1-patch1";
127 src = pkgs.fetchgit {
128 url = "https://code.rhodecode.com/upstream/pylons";
129 rev = "707354ee4261b9c10450404fc9852ccea4fd667d";
130 sha256 = "b2763274c2780523a335f83a1df65be22ebe4ff413a7bc9e9288d23c1f62032e";
131 };
122 name = "Pylons-1.0.2.rhodecode-patch1";
132 123 });
133 124
134 125 pyramid = super.pyramid.override (attrs: {
135 126 postFixup = ''
136 127 wrapPythonPrograms
137 128 # TODO: johbo: "wrapPython" adds this magic line which
138 129 # confuses pserve.
139 130 ${sed} '/import sys; sys.argv/d' $out/bin/.pserve-wrapped
140 131 '';
141 132 meta = {
142 133 license = localLicenses.repoze;
143 134 };
144 135 });
145 136
146 137 pyramid-debugtoolbar = super.pyramid-debugtoolbar.override (attrs: {
147 138 meta = {
148 139 license = [ pkgs.lib.licenses.bsdOriginal localLicenses.repoze ];
149 140 };
150 141 });
151 142
152 Pyro4 = super.Pyro4.override (attrs: {
153 # TODO: Was not able to generate this version, needs further
154 # investigation.
155 name = "Pyro4-4.35";
156 src = pkgs.fetchurl {
157 url = "https://pypi.python.org/packages/source/P/Pyro4/Pyro4-4.35.src.tar.gz";
158 md5 = "cbe6cb855f086a0f092ca075005855f3";
159 };
160 });
161
162 143 pysqlite = super.pysqlite.override (attrs: {
163 144 propagatedBuildInputs = [
164 145 pkgs.sqlite
165 146 ];
166 147 meta = {
167 148 license = [ pkgs.lib.licenses.zlib pkgs.lib.licenses.libpng ];
168 149 };
169 150 });
170 151
171 152 pytest-runner = super.pytest-runner.override (attrs: {
172 153 propagatedBuildInputs = [
173 154 self.setuptools-scm
174 155 ];
175 156 });
176 157
177 158 python-ldap = super.python-ldap.override (attrs: {
178 159 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
179 160 pkgs.cyrus_sasl
180 161 pkgs.openldap
181 162 pkgs.openssl
182 163 ];
183 164 # TODO: johbo: Remove the "or" once we drop 16.03 support.
184 165 NIX_CFLAGS_COMPILE = "-I${pkgs.cyrus_sasl.dev or pkgs.cyrus_sasl}/include/sasl";
185 166 });
186 167
187 168 python-pam = super.python-pam.override (attrs:
188 169 let
189 170 includeLibPam = pkgs.stdenv.isLinux;
190 171 in {
191 172 # TODO: johbo: Move the option up into the default.nix, we should
192 173 # include python-pam only on supported platforms.
193 174 propagatedBuildInputs = attrs.propagatedBuildInputs ++
194 175 pkgs.lib.optional includeLibPam [
195 176 pkgs.pam
196 177 ];
197 178 # TODO: johbo: Check if this can be avoided, or transform into
198 179 # a real patch
199 180 patchPhase = pkgs.lib.optionals includeLibPam ''
200 181 substituteInPlace pam.py \
201 182 --replace 'find_library("pam")' '"${pkgs.pam}/lib/libpam.so.0"'
202 183 '';
203 184 });
204 185
205 rhodecode-tools = super.rhodecode-tools.override (attrs: {
206 patches = [
207 ./patch-rhodecode-tools-setup.diff
208 ];
209 });
210
211 186 URLObject = super.URLObject.override (attrs: {
212 187 meta = {
213 188 license = {
214 189 spdxId = "Unlicense";
215 190 fullName = "The Unlicense";
216 191 url = http://unlicense.org/;
217 192 };
218 193 };
219 194 });
220 195
221 196 amqplib = super.amqplib.override (attrs: {
222 197 meta = {
223 198 license = pkgs.lib.licenses.lgpl3;
224 199 };
225 200 });
226 201
227 202 docutils = super.docutils.override (attrs: {
228 203 meta = {
229 204 license = pkgs.lib.licenses.bsd2;
230 205 };
231 206 });
232 207
233 208 colander = super.colander.override (attrs: {
234 209 meta = {
235 210 license = localLicenses.repoze;
236 211 };
237 212 });
238 213
239 214 pyramid-beaker = super.pyramid-beaker.override (attrs: {
240 215 meta = {
241 216 license = localLicenses.repoze;
242 217 };
243 218 });
244 219
245 220 pyramid-mako = super.pyramid-mako.override (attrs: {
246 221 meta = {
247 222 license = localLicenses.repoze;
248 223 };
249 224 });
250 225
251 226 repoze.lru = super.repoze.lru.override (attrs: {
252 227 meta = {
253 228 license = localLicenses.repoze;
254 229 };
255 230 });
256 231
257 232 recaptcha-client = super.recaptcha-client.override (attrs: {
258 233 meta = {
259 234 # TODO: It is MIT/X11
260 235 license = pkgs.lib.licenses.mit;
261 236 };
262 237 });
263 238
264 239 python-editor = super.python-editor.override (attrs: {
265 240 meta = {
266 241 license = pkgs.lib.licenses.asl20;
267 242 };
268 243 });
269 244
270 245 translationstring = super.translationstring.override (attrs: {
271 246 meta = {
272 247 license = localLicenses.repoze;
273 248 };
274 249 });
275 250
276 251 venusian = super.venusian.override (attrs: {
277 252 meta = {
278 253 license = localLicenses.repoze;
279 254 };
280 255 });
281 256
282 257 # Avoid that setuptools is replaced, this leads to trouble
283 258 # with buildPythonPackage.
284 259 setuptools = basePythonPackages.setuptools;
285 260
286 261 }
@@ -1,1864 +1,1852 b''
1 1 # Generated by pip2nix 0.4.0
2 2 # See https://github.com/johbo/pip2nix
3 3
4 4 {
5 5 Babel = super.buildPythonPackage {
6 6 name = "Babel-1.3";
7 7 buildInputs = with self; [];
8 8 doCheck = false;
9 9 propagatedBuildInputs = with self; [pytz];
10 10 src = fetchurl {
11 11 url = "https://pypi.python.org/packages/33/27/e3978243a03a76398c384c83f7ca879bc6e8f1511233a621fcada135606e/Babel-1.3.tar.gz";
12 12 md5 = "5264ceb02717843cbc9ffce8e6e06bdb";
13 13 };
14 14 meta = {
15 15 license = [ pkgs.lib.licenses.bsdOriginal ];
16 16 };
17 17 };
18 18 Beaker = super.buildPythonPackage {
19 19 name = "Beaker-1.7.0";
20 20 buildInputs = with self; [];
21 21 doCheck = false;
22 22 propagatedBuildInputs = with self; [];
23 23 src = fetchurl {
24 24 url = "https://pypi.python.org/packages/97/8e/409d2e7c009b8aa803dc9e6f239f1db7c3cdf578249087a404e7c27a505d/Beaker-1.7.0.tar.gz";
25 25 md5 = "386be3f7fe427358881eee4622b428b3";
26 26 };
27 27 meta = {
28 28 license = [ pkgs.lib.licenses.bsdOriginal ];
29 29 };
30 30 };
31 31 CProfileV = super.buildPythonPackage {
32 32 name = "CProfileV-1.0.6";
33 33 buildInputs = with self; [];
34 34 doCheck = false;
35 35 propagatedBuildInputs = with self; [bottle];
36 36 src = fetchurl {
37 37 url = "https://pypi.python.org/packages/eb/df/983a0b6cfd3ac94abf023f5011cb04f33613ace196e33f53c86cf91850d5/CProfileV-1.0.6.tar.gz";
38 38 md5 = "08c7c242b6e64237bc53c5d13537e03d";
39 39 };
40 40 meta = {
41 41 license = [ pkgs.lib.licenses.mit ];
42 42 };
43 43 };
44 44 Chameleon = super.buildPythonPackage {
45 45 name = "Chameleon-2.24";
46 46 buildInputs = with self; [];
47 47 doCheck = false;
48 48 propagatedBuildInputs = with self; [];
49 49 src = fetchurl {
50 50 url = "https://pypi.python.org/packages/5a/9e/637379ffa13c5172b5c0e704833ffea6bf51cec7567f93fd6e903d53ed74/Chameleon-2.24.tar.gz";
51 51 md5 = "1b01f1f6533a8a11d0d2f2366dec5342";
52 52 };
53 53 meta = {
54 54 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
55 55 };
56 56 };
57 57 FormEncode = super.buildPythonPackage {
58 58 name = "FormEncode-1.2.4";
59 59 buildInputs = with self; [];
60 60 doCheck = false;
61 61 propagatedBuildInputs = with self; [];
62 62 src = fetchurl {
63 63 url = "https://pypi.python.org/packages/8e/59/0174271a6f004512e0201188593e6d319db139d14cb7490e488bbb078015/FormEncode-1.2.4.tar.gz";
64 64 md5 = "6bc17fb9aed8aea198975e888e2077f4";
65 65 };
66 66 meta = {
67 67 license = [ pkgs.lib.licenses.psfl ];
68 68 };
69 69 };
70 70 Jinja2 = super.buildPythonPackage {
71 71 name = "Jinja2-2.7.3";
72 72 buildInputs = with self; [];
73 73 doCheck = false;
74 74 propagatedBuildInputs = with self; [MarkupSafe];
75 75 src = fetchurl {
76 76 url = "https://pypi.python.org/packages/b0/73/eab0bca302d6d6a0b5c402f47ad1760dc9cb2dd14bbc1873ad48db258e4d/Jinja2-2.7.3.tar.gz";
77 77 md5 = "b9dffd2f3b43d673802fe857c8445b1a";
78 78 };
79 79 meta = {
80 80 license = [ pkgs.lib.licenses.bsdOriginal ];
81 81 };
82 82 };
83 83 Mako = super.buildPythonPackage {
84 name = "Mako-1.0.1";
84 name = "Mako-1.0.6";
85 85 buildInputs = with self; [];
86 86 doCheck = false;
87 87 propagatedBuildInputs = with self; [MarkupSafe];
88 88 src = fetchurl {
89 url = "https://pypi.python.org/packages/8e/a4/aa56533ecaa5f22ca92428f74e074d0c9337282933c722391902c8f9e0f8/Mako-1.0.1.tar.gz";
90 md5 = "9f0aafd177b039ef67b90ea350497a54";
89 url = "https://pypi.python.org/packages/56/4b/cb75836863a6382199aefb3d3809937e21fa4cb0db15a4f4ba0ecc2e7e8e/Mako-1.0.6.tar.gz";
90 md5 = "a28e22a339080316b2acc352b9ee631c";
91 91 };
92 92 meta = {
93 93 license = [ pkgs.lib.licenses.mit ];
94 94 };
95 95 };
96 96 Markdown = super.buildPythonPackage {
97 name = "Markdown-2.6.2";
97 name = "Markdown-2.6.7";
98 98 buildInputs = with self; [];
99 99 doCheck = false;
100 100 propagatedBuildInputs = with self; [];
101 101 src = fetchurl {
102 url = "https://pypi.python.org/packages/62/8b/83658b5f6c220d5fcde9f9852d46ea54765d734cfbc5a9f4c05bfc36db4d/Markdown-2.6.2.tar.gz";
103 md5 = "256d19afcc564dc4ce4c229bb762f7ae";
102 url = "https://pypi.python.org/packages/48/a4/fc6b002789c2239ac620ca963694c95b8f74e4747769cdf6021276939e74/Markdown-2.6.7.zip";
103 md5 = "632710a7474bbb74a82084392251061f";
104 104 };
105 105 meta = {
106 106 license = [ pkgs.lib.licenses.bsdOriginal ];
107 107 };
108 108 };
109 109 MarkupSafe = super.buildPythonPackage {
110 110 name = "MarkupSafe-0.23";
111 111 buildInputs = with self; [];
112 112 doCheck = false;
113 113 propagatedBuildInputs = with self; [];
114 114 src = fetchurl {
115 115 url = "https://pypi.python.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-0.23.tar.gz";
116 116 md5 = "f5ab3deee4c37cd6a922fb81e730da6e";
117 117 };
118 118 meta = {
119 119 license = [ pkgs.lib.licenses.bsdOriginal ];
120 120 };
121 121 };
122 122 MySQL-python = super.buildPythonPackage {
123 123 name = "MySQL-python-1.2.5";
124 124 buildInputs = with self; [];
125 125 doCheck = false;
126 126 propagatedBuildInputs = with self; [];
127 127 src = fetchurl {
128 128 url = "https://pypi.python.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip";
129 129 md5 = "654f75b302db6ed8dc5a898c625e030c";
130 130 };
131 131 meta = {
132 132 license = [ pkgs.lib.licenses.gpl1 ];
133 133 };
134 134 };
135 135 Paste = super.buildPythonPackage {
136 name = "Paste-2.0.2";
136 name = "Paste-2.0.3";
137 137 buildInputs = with self; [];
138 138 doCheck = false;
139 139 propagatedBuildInputs = with self; [six];
140 140 src = fetchurl {
141 url = "https://pypi.python.org/packages/d5/8d/0f8ac40687b97ff3e07ebd1369be20bdb3f93864d2dc3c2ff542edb4ce50/Paste-2.0.2.tar.gz";
142 md5 = "4bfc8a7eaf858f6309d2ac0f40fc951c";
141 url = "https://pypi.python.org/packages/30/c3/5c2f7c7a02e4f58d4454353fa1c32c94f79fa4e36d07a67c0ac295ea369e/Paste-2.0.3.tar.gz";
142 md5 = "1231e14eae62fa7ed76e9130b04bc61e";
143 143 };
144 144 meta = {
145 145 license = [ pkgs.lib.licenses.mit ];
146 146 };
147 147 };
148 148 PasteDeploy = super.buildPythonPackage {
149 149 name = "PasteDeploy-1.5.2";
150 150 buildInputs = with self; [];
151 151 doCheck = false;
152 152 propagatedBuildInputs = with self; [];
153 153 src = fetchurl {
154 154 url = "https://pypi.python.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz";
155 155 md5 = "352b7205c78c8de4987578d19431af3b";
156 156 };
157 157 meta = {
158 158 license = [ pkgs.lib.licenses.mit ];
159 159 };
160 160 };
161 161 PasteScript = super.buildPythonPackage {
162 162 name = "PasteScript-1.7.5";
163 163 buildInputs = with self; [];
164 164 doCheck = false;
165 165 propagatedBuildInputs = with self; [Paste PasteDeploy];
166 166 src = fetchurl {
167 167 url = "https://pypi.python.org/packages/a5/05/fc60efa7c2f17a1dbaeccb2a903a1e90902d92b9d00eebabe3095829d806/PasteScript-1.7.5.tar.gz";
168 168 md5 = "4c72d78dcb6bb993f30536842c16af4d";
169 169 };
170 170 meta = {
171 171 license = [ pkgs.lib.licenses.mit ];
172 172 };
173 173 };
174 174 Pygments = super.buildPythonPackage {
175 name = "Pygments-2.1.3";
175 name = "Pygments-2.2.0";
176 176 buildInputs = with self; [];
177 177 doCheck = false;
178 178 propagatedBuildInputs = with self; [];
179 179 src = fetchurl {
180 url = "https://pypi.python.org/packages/b8/67/ab177979be1c81bc99c8d0592ef22d547e70bb4c6815c383286ed5dec504/Pygments-2.1.3.tar.gz";
181 md5 = "ed3fba2467c8afcda4d317e4ef2c6150";
180 url = "https://pypi.python.org/packages/71/2a/2e4e77803a8bd6408a2903340ac498cb0a2181811af7c9ec92cb70b0308a/Pygments-2.2.0.tar.gz";
181 md5 = "13037baca42f16917cbd5ad2fab50844";
182 182 };
183 183 meta = {
184 184 license = [ pkgs.lib.licenses.bsdOriginal ];
185 185 };
186 186 };
187 187 Pylons = super.buildPythonPackage {
188 name = "Pylons-1.0.1";
188 name = "Pylons-1.0.2.dev20161213";
189 189 buildInputs = with self; [];
190 190 doCheck = false;
191 191 propagatedBuildInputs = with self; [Routes WebHelpers Beaker Paste PasteDeploy PasteScript FormEncode simplejson decorator nose Mako WebError WebTest Tempita MarkupSafe WebOb];
192 192 src = fetchurl {
193 url = "https://pypi.python.org/packages/a2/69/b835a6bad00acbfeed3f33c6e44fa3f936efc998c795bfb15c61a79ecf62/Pylons-1.0.1.tar.gz";
194 md5 = "6cb880d75fa81213192142b07a6e4915";
193 url = "https://code.rhodecode.com/upstream/pylons/archive/707354ee4261b9c10450404fc9852ccea4fd667d.tar.gz?md5=f26633726fa2cd3a340316ee6a5d218f";
194 md5 = "f26633726fa2cd3a340316ee6a5d218f";
195 195 };
196 196 meta = {
197 197 license = [ pkgs.lib.licenses.bsdOriginal ];
198 198 };
199 199 };
200 200 Pyro4 = super.buildPythonPackage {
201 201 name = "Pyro4-4.41";
202 202 buildInputs = with self; [];
203 203 doCheck = false;
204 204 propagatedBuildInputs = with self; [serpent];
205 205 src = fetchurl {
206 206 url = "https://pypi.python.org/packages/56/2b/89b566b4bf3e7f8ba790db2d1223852f8cb454c52cab7693dd41f608ca2a/Pyro4-4.41.tar.gz";
207 207 md5 = "ed69e9bfafa9c06c049a87cb0c4c2b6c";
208 208 };
209 209 meta = {
210 210 license = [ pkgs.lib.licenses.mit ];
211 211 };
212 212 };
213 213 Routes = super.buildPythonPackage {
214 214 name = "Routes-1.13";
215 215 buildInputs = with self; [];
216 216 doCheck = false;
217 217 propagatedBuildInputs = with self; [repoze.lru];
218 218 src = fetchurl {
219 219 url = "https://pypi.python.org/packages/88/d3/259c3b3cde8837eb9441ab5f574a660e8a4acea8f54a078441d4d2acac1c/Routes-1.13.tar.gz";
220 220 md5 = "d527b0ab7dd9172b1275a41f97448783";
221 221 };
222 222 meta = {
223 223 license = [ pkgs.lib.licenses.bsdOriginal ];
224 224 };
225 225 };
226 226 SQLAlchemy = super.buildPythonPackage {
227 227 name = "SQLAlchemy-0.9.9";
228 228 buildInputs = with self; [];
229 229 doCheck = false;
230 230 propagatedBuildInputs = with self; [];
231 231 src = fetchurl {
232 232 url = "https://pypi.python.org/packages/28/f7/1bbfd0d8597e8c358d5e15a166a486ad82fc5579b4e67b6ef7c05b1d182b/SQLAlchemy-0.9.9.tar.gz";
233 233 md5 = "8a10a9bd13ed3336ef7333ac2cc679ff";
234 234 };
235 235 meta = {
236 236 license = [ pkgs.lib.licenses.mit ];
237 237 };
238 238 };
239 239 Sphinx = super.buildPythonPackage {
240 240 name = "Sphinx-1.2.2";
241 241 buildInputs = with self; [];
242 242 doCheck = false;
243 243 propagatedBuildInputs = with self; [Pygments docutils Jinja2];
244 244 src = fetchurl {
245 245 url = "https://pypi.python.org/packages/0a/50/34017e6efcd372893a416aba14b84a1a149fc7074537b0e9cb6ca7b7abe9/Sphinx-1.2.2.tar.gz";
246 246 md5 = "3dc73ccaa8d0bfb2d62fb671b1f7e8a4";
247 247 };
248 248 meta = {
249 249 license = [ pkgs.lib.licenses.bsdOriginal ];
250 250 };
251 251 };
252 252 Tempita = super.buildPythonPackage {
253 253 name = "Tempita-0.5.2";
254 254 buildInputs = with self; [];
255 255 doCheck = false;
256 256 propagatedBuildInputs = with self; [];
257 257 src = fetchurl {
258 258 url = "https://pypi.python.org/packages/56/c8/8ed6eee83dbddf7b0fc64dd5d4454bc05e6ccaafff47991f73f2894d9ff4/Tempita-0.5.2.tar.gz";
259 259 md5 = "4c2f17bb9d481821c41b6fbee904cea1";
260 260 };
261 261 meta = {
262 262 license = [ pkgs.lib.licenses.mit ];
263 263 };
264 264 };
265 265 URLObject = super.buildPythonPackage {
266 266 name = "URLObject-2.4.0";
267 267 buildInputs = with self; [];
268 268 doCheck = false;
269 269 propagatedBuildInputs = with self; [];
270 270 src = fetchurl {
271 271 url = "https://pypi.python.org/packages/cb/b6/e25e58500f9caef85d664bec71ec67c116897bfebf8622c32cb75d1ca199/URLObject-2.4.0.tar.gz";
272 272 md5 = "2ed819738a9f0a3051f31dc9924e3065";
273 273 };
274 274 meta = {
275 275 license = [ ];
276 276 };
277 277 };
278 278 WebError = super.buildPythonPackage {
279 279 name = "WebError-0.10.3";
280 280 buildInputs = with self; [];
281 281 doCheck = false;
282 282 propagatedBuildInputs = with self; [WebOb Tempita Pygments Paste];
283 283 src = fetchurl {
284 284 url = "https://pypi.python.org/packages/35/76/e7e5c2ce7e9c7f31b54c1ff295a495886d1279a002557d74dd8957346a79/WebError-0.10.3.tar.gz";
285 285 md5 = "84b9990b0baae6fd440b1e60cdd06f9a";
286 286 };
287 287 meta = {
288 288 license = [ pkgs.lib.licenses.mit ];
289 289 };
290 290 };
291 291 WebHelpers = super.buildPythonPackage {
292 292 name = "WebHelpers-1.3";
293 293 buildInputs = with self; [];
294 294 doCheck = false;
295 295 propagatedBuildInputs = with self; [MarkupSafe];
296 296 src = fetchurl {
297 297 url = "https://pypi.python.org/packages/ee/68/4d07672821d514184357f1552f2dad923324f597e722de3b016ca4f7844f/WebHelpers-1.3.tar.gz";
298 298 md5 = "32749ffadfc40fea51075a7def32588b";
299 299 };
300 300 meta = {
301 301 license = [ pkgs.lib.licenses.bsdOriginal ];
302 302 };
303 303 };
304 304 WebHelpers2 = super.buildPythonPackage {
305 305 name = "WebHelpers2-2.0";
306 306 buildInputs = with self; [];
307 307 doCheck = false;
308 308 propagatedBuildInputs = with self; [MarkupSafe six];
309 309 src = fetchurl {
310 310 url = "https://pypi.python.org/packages/ff/30/56342c6ea522439e3662427c8d7b5e5b390dff4ff2dc92d8afcb8ab68b75/WebHelpers2-2.0.tar.gz";
311 311 md5 = "0f6b68d70c12ee0aed48c00b24da13d3";
312 312 };
313 313 meta = {
314 314 license = [ pkgs.lib.licenses.mit ];
315 315 };
316 316 };
317 317 WebOb = super.buildPythonPackage {
318 318 name = "WebOb-1.3.1";
319 319 buildInputs = with self; [];
320 320 doCheck = false;
321 321 propagatedBuildInputs = with self; [];
322 322 src = fetchurl {
323 323 url = "https://pypi.python.org/packages/16/78/adfc0380b8a0d75b2d543fa7085ba98a573b1ae486d9def88d172b81b9fa/WebOb-1.3.1.tar.gz";
324 324 md5 = "20918251c5726956ba8fef22d1556177";
325 325 };
326 326 meta = {
327 327 license = [ pkgs.lib.licenses.mit ];
328 328 };
329 329 };
330 330 WebTest = super.buildPythonPackage {
331 331 name = "WebTest-1.4.3";
332 332 buildInputs = with self; [];
333 333 doCheck = false;
334 334 propagatedBuildInputs = with self; [WebOb];
335 335 src = fetchurl {
336 336 url = "https://pypi.python.org/packages/51/3d/84fd0f628df10b30c7db87895f56d0158e5411206b721ca903cb51bfd948/WebTest-1.4.3.zip";
337 337 md5 = "631ce728bed92c681a4020a36adbc353";
338 338 };
339 339 meta = {
340 340 license = [ pkgs.lib.licenses.mit ];
341 341 };
342 342 };
343 343 Whoosh = super.buildPythonPackage {
344 name = "Whoosh-2.7.0";
344 name = "Whoosh-2.7.4";
345 345 buildInputs = with self; [];
346 346 doCheck = false;
347 347 propagatedBuildInputs = with self; [];
348 348 src = fetchurl {
349 url = "https://pypi.python.org/packages/1c/dc/2f0231ff3875ded36df8c1ab851451e51a237dc0e5a86d3d96036158da94/Whoosh-2.7.0.zip";
350 md5 = "7abfd970f16fadc7311960f3fa0bc7a9";
349 url = "https://pypi.python.org/packages/25/2b/6beed2107b148edc1321da0d489afc4617b9ed317ef7b72d4993cad9b684/Whoosh-2.7.4.tar.gz";
350 md5 = "c2710105f20b3e29936bd2357383c325";
351 351 };
352 352 meta = {
353 353 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ];
354 354 };
355 355 };
356 356 alembic = super.buildPythonPackage {
357 357 name = "alembic-0.8.4";
358 358 buildInputs = with self; [];
359 359 doCheck = false;
360 360 propagatedBuildInputs = with self; [SQLAlchemy Mako python-editor];
361 361 src = fetchurl {
362 362 url = "https://pypi.python.org/packages/ca/7e/299b4499b5c75e5a38c5845145ad24755bebfb8eec07a2e1c366b7181eeb/alembic-0.8.4.tar.gz";
363 363 md5 = "5f95d8ee62b443f9b37eb5bee76c582d";
364 364 };
365 365 meta = {
366 366 license = [ pkgs.lib.licenses.mit ];
367 367 };
368 368 };
369 369 amqplib = super.buildPythonPackage {
370 370 name = "amqplib-1.0.2";
371 371 buildInputs = with self; [];
372 372 doCheck = false;
373 373 propagatedBuildInputs = with self; [];
374 374 src = fetchurl {
375 375 url = "https://pypi.python.org/packages/75/b7/8c2429bf8d92354a0118614f9a4d15e53bc69ebedce534284111de5a0102/amqplib-1.0.2.tgz";
376 376 md5 = "5c92f17fbedd99b2b4a836d4352d1e2f";
377 377 };
378 378 meta = {
379 379 license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
380 380 };
381 381 };
382 382 anyjson = super.buildPythonPackage {
383 383 name = "anyjson-0.3.3";
384 384 buildInputs = with self; [];
385 385 doCheck = false;
386 386 propagatedBuildInputs = with self; [];
387 387 src = fetchurl {
388 388 url = "https://pypi.python.org/packages/c3/4d/d4089e1a3dd25b46bebdb55a992b0797cff657b4477bc32ce28038fdecbc/anyjson-0.3.3.tar.gz";
389 389 md5 = "2ea28d6ec311aeeebaf993cb3008b27c";
390 390 };
391 391 meta = {
392 392 license = [ pkgs.lib.licenses.bsdOriginal ];
393 393 };
394 394 };
395 395 appenlight-client = super.buildPythonPackage {
396 396 name = "appenlight-client-0.6.14";
397 397 buildInputs = with self; [];
398 398 doCheck = false;
399 399 propagatedBuildInputs = with self; [WebOb requests];
400 400 src = fetchurl {
401 401 url = "https://pypi.python.org/packages/4d/e0/23fee3ebada8143f707e65c06bcb82992040ee64ea8355e044ed55ebf0c1/appenlight_client-0.6.14.tar.gz";
402 402 md5 = "578c69b09f4356d898fff1199b98a95c";
403 403 };
404 404 meta = {
405 405 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "DFSG approved"; } ];
406 406 };
407 407 };
408 408 authomatic = super.buildPythonPackage {
409 409 name = "authomatic-0.1.0.post1";
410 410 buildInputs = with self; [];
411 411 doCheck = false;
412 412 propagatedBuildInputs = with self; [];
413 413 src = fetchurl {
414 414 url = "https://pypi.python.org/packages/08/1a/8a930461e604c2d5a7a871e1ac59fa82ccf994c32e807230c8d2fb07815a/Authomatic-0.1.0.post1.tar.gz";
415 415 md5 = "be3f3ce08747d776aae6d6cc8dcb49a9";
416 416 };
417 417 meta = {
418 418 license = [ pkgs.lib.licenses.mit ];
419 419 };
420 420 };
421 421 backport-ipaddress = super.buildPythonPackage {
422 422 name = "backport-ipaddress-0.1";
423 423 buildInputs = with self; [];
424 424 doCheck = false;
425 425 propagatedBuildInputs = with self; [];
426 426 src = fetchurl {
427 427 url = "https://pypi.python.org/packages/d3/30/54c6dab05a4dec44db25ff309f1fbb6b7a8bde3f2bade38bb9da67bbab8f/backport_ipaddress-0.1.tar.gz";
428 428 md5 = "9c1f45f4361f71b124d7293a60006c05";
429 429 };
430 430 meta = {
431 431 license = [ pkgs.lib.licenses.psfl ];
432 432 };
433 433 };
434 434 backports.shutil-get-terminal-size = super.buildPythonPackage {
435 435 name = "backports.shutil-get-terminal-size-1.0.0";
436 436 buildInputs = with self; [];
437 437 doCheck = false;
438 438 propagatedBuildInputs = with self; [];
439 439 src = fetchurl {
440 440 url = "https://pypi.python.org/packages/ec/9c/368086faa9c016efce5da3e0e13ba392c9db79e3ab740b763fe28620b18b/backports.shutil_get_terminal_size-1.0.0.tar.gz";
441 441 md5 = "03267762480bd86b50580dc19dff3c66";
442 442 };
443 443 meta = {
444 444 license = [ pkgs.lib.licenses.mit ];
445 445 };
446 446 };
447 447 bottle = super.buildPythonPackage {
448 448 name = "bottle-0.12.8";
449 449 buildInputs = with self; [];
450 450 doCheck = false;
451 451 propagatedBuildInputs = with self; [];
452 452 src = fetchurl {
453 453 url = "https://pypi.python.org/packages/52/df/e4a408f3a7af396d186d4ecd3b389dd764f0f943b4fa8d257bfe7b49d343/bottle-0.12.8.tar.gz";
454 454 md5 = "13132c0a8f607bf860810a6ee9064c5b";
455 455 };
456 456 meta = {
457 457 license = [ pkgs.lib.licenses.mit ];
458 458 };
459 459 };
460 460 bumpversion = super.buildPythonPackage {
461 461 name = "bumpversion-0.5.3";
462 462 buildInputs = with self; [];
463 463 doCheck = false;
464 464 propagatedBuildInputs = with self; [];
465 465 src = fetchurl {
466 466 url = "https://pypi.python.org/packages/14/41/8c9da3549f8e00c84f0432c3a8cf8ed6898374714676aab91501d48760db/bumpversion-0.5.3.tar.gz";
467 467 md5 = "c66a3492eafcf5ad4b024be9fca29820";
468 468 };
469 469 meta = {
470 470 license = [ pkgs.lib.licenses.mit ];
471 471 };
472 472 };
473 473 celery = super.buildPythonPackage {
474 474 name = "celery-2.2.10";
475 475 buildInputs = with self; [];
476 476 doCheck = false;
477 477 propagatedBuildInputs = with self; [python-dateutil anyjson kombu pyparsing];
478 478 src = fetchurl {
479 479 url = "https://pypi.python.org/packages/b1/64/860fd50e45844c83442e7953effcddeff66b2851d90b2d784f7201c111b8/celery-2.2.10.tar.gz";
480 480 md5 = "898bc87e54f278055b561316ba73e222";
481 481 };
482 482 meta = {
483 483 license = [ pkgs.lib.licenses.bsdOriginal ];
484 484 };
485 485 };
486 486 channelstream = super.buildPythonPackage {
487 487 name = "channelstream-0.5.2";
488 488 buildInputs = with self; [];
489 489 doCheck = false;
490 490 propagatedBuildInputs = with self; [gevent ws4py pyramid pyramid-jinja2 itsdangerous requests six];
491 491 src = fetchurl {
492 492 url = "https://pypi.python.org/packages/2b/31/29a8e085cf5bf97fa88e7b947adabfc581a18a3463adf77fb6dada34a65f/channelstream-0.5.2.tar.gz";
493 493 md5 = "1c5eb2a8a405be6f1073da94da6d81d3";
494 494 };
495 495 meta = {
496 496 license = [ pkgs.lib.licenses.bsdOriginal ];
497 497 };
498 498 };
499 499 click = super.buildPythonPackage {
500 500 name = "click-5.1";
501 501 buildInputs = with self; [];
502 502 doCheck = false;
503 503 propagatedBuildInputs = with self; [];
504 504 src = fetchurl {
505 505 url = "https://pypi.python.org/packages/b7/34/a496632c4fb6c1ee76efedf77bb8d28b29363d839953d95095b12defe791/click-5.1.tar.gz";
506 506 md5 = "9c5323008cccfe232a8b161fc8196d41";
507 507 };
508 508 meta = {
509 509 license = [ pkgs.lib.licenses.bsdOriginal ];
510 510 };
511 511 };
512 512 colander = super.buildPythonPackage {
513 513 name = "colander-1.2";
514 514 buildInputs = with self; [];
515 515 doCheck = false;
516 516 propagatedBuildInputs = with self; [translationstring iso8601];
517 517 src = fetchurl {
518 518 url = "https://pypi.python.org/packages/14/23/c9ceba07a6a1dc0eefbb215fc0dc64aabc2b22ee756bc0f0c13278fa0887/colander-1.2.tar.gz";
519 519 md5 = "83db21b07936a0726e588dae1914b9ed";
520 520 };
521 521 meta = {
522 522 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
523 523 };
524 524 };
525 525 configobj = super.buildPythonPackage {
526 526 name = "configobj-5.0.6";
527 527 buildInputs = with self; [];
528 528 doCheck = false;
529 529 propagatedBuildInputs = with self; [six];
530 530 src = fetchurl {
531 531 url = "https://pypi.python.org/packages/64/61/079eb60459c44929e684fa7d9e2fdca403f67d64dd9dbac27296be2e0fab/configobj-5.0.6.tar.gz";
532 532 md5 = "e472a3a1c2a67bb0ec9b5d54c13a47d6";
533 533 };
534 534 meta = {
535 535 license = [ pkgs.lib.licenses.bsdOriginal ];
536 536 };
537 537 };
538 538 cov-core = super.buildPythonPackage {
539 539 name = "cov-core-1.15.0";
540 540 buildInputs = with self; [];
541 541 doCheck = false;
542 542 propagatedBuildInputs = with self; [coverage];
543 543 src = fetchurl {
544 544 url = "https://pypi.python.org/packages/4b/87/13e75a47b4ba1be06f29f6d807ca99638bedc6b57fa491cd3de891ca2923/cov-core-1.15.0.tar.gz";
545 545 md5 = "f519d4cb4c4e52856afb14af52919fe6";
546 546 };
547 547 meta = {
548 548 license = [ pkgs.lib.licenses.mit ];
549 549 };
550 550 };
551 551 coverage = super.buildPythonPackage {
552 552 name = "coverage-3.7.1";
553 553 buildInputs = with self; [];
554 554 doCheck = false;
555 555 propagatedBuildInputs = with self; [];
556 556 src = fetchurl {
557 557 url = "https://pypi.python.org/packages/09/4f/89b06c7fdc09687bca507dc411c342556ef9c5a3b26756137a4878ff19bf/coverage-3.7.1.tar.gz";
558 558 md5 = "c47b36ceb17eaff3ecfab3bcd347d0df";
559 559 };
560 560 meta = {
561 561 license = [ pkgs.lib.licenses.bsdOriginal ];
562 562 };
563 563 };
564 564 cssselect = super.buildPythonPackage {
565 565 name = "cssselect-0.9.1";
566 566 buildInputs = with self; [];
567 567 doCheck = false;
568 568 propagatedBuildInputs = with self; [];
569 569 src = fetchurl {
570 570 url = "https://pypi.python.org/packages/aa/e5/9ee1460d485b94a6d55732eb7ad5b6c084caf73dd6f9cb0bb7d2a78fafe8/cssselect-0.9.1.tar.gz";
571 571 md5 = "c74f45966277dc7a0f768b9b0f3522ac";
572 572 };
573 573 meta = {
574 574 license = [ pkgs.lib.licenses.bsdOriginal ];
575 575 };
576 576 };
577 577 decorator = super.buildPythonPackage {
578 578 name = "decorator-3.4.2";
579 579 buildInputs = with self; [];
580 580 doCheck = false;
581 581 propagatedBuildInputs = with self; [];
582 582 src = fetchurl {
583 583 url = "https://pypi.python.org/packages/35/3a/42566eb7a2cbac774399871af04e11d7ae3fc2579e7dae85213b8d1d1c57/decorator-3.4.2.tar.gz";
584 584 md5 = "9e0536870d2b83ae27d58dbf22582f4d";
585 585 };
586 586 meta = {
587 587 license = [ pkgs.lib.licenses.bsdOriginal ];
588 588 };
589 589 };
590 590 deform = super.buildPythonPackage {
591 591 name = "deform-2.0a2";
592 592 buildInputs = with self; [];
593 593 doCheck = false;
594 594 propagatedBuildInputs = with self; [Chameleon colander peppercorn translationstring zope.deprecation];
595 595 src = fetchurl {
596 596 url = "https://pypi.python.org/packages/8d/b3/aab57e81da974a806dc9c5fa024a6404720f890a6dcf2e80885e3cb4609a/deform-2.0a2.tar.gz";
597 597 md5 = "7a90d41f7fbc18002ce74f39bd90a5e4";
598 598 };
599 599 meta = {
600 600 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
601 601 };
602 602 };
603 603 docutils = super.buildPythonPackage {
604 604 name = "docutils-0.12";
605 605 buildInputs = with self; [];
606 606 doCheck = false;
607 607 propagatedBuildInputs = with self; [];
608 608 src = fetchurl {
609 609 url = "https://pypi.python.org/packages/37/38/ceda70135b9144d84884ae2fc5886c6baac4edea39550f28bcd144c1234d/docutils-0.12.tar.gz";
610 610 md5 = "4622263b62c5c771c03502afa3157768";
611 611 };
612 612 meta = {
613 613 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.publicDomain pkgs.lib.licenses.gpl1 { fullName = "public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)"; } pkgs.lib.licenses.psfl ];
614 614 };
615 615 };
616 616 dogpile.cache = super.buildPythonPackage {
617 617 name = "dogpile.cache-0.6.1";
618 618 buildInputs = with self; [];
619 619 doCheck = false;
620 620 propagatedBuildInputs = with self; [];
621 621 src = fetchurl {
622 622 url = "https://pypi.python.org/packages/f6/a0/6f2142c58c6588d17c734265b103ae1cd0741e1681dd9483a63f22033375/dogpile.cache-0.6.1.tar.gz";
623 623 md5 = "35d7fb30f22bbd0685763d894dd079a9";
624 624 };
625 625 meta = {
626 626 license = [ pkgs.lib.licenses.bsdOriginal ];
627 627 };
628 628 };
629 629 dogpile.core = super.buildPythonPackage {
630 630 name = "dogpile.core-0.4.1";
631 631 buildInputs = with self; [];
632 632 doCheck = false;
633 633 propagatedBuildInputs = with self; [];
634 634 src = fetchurl {
635 635 url = "https://pypi.python.org/packages/0e/77/e72abc04c22aedf874301861e5c1e761231c288b5de369c18be8f4b5c9bb/dogpile.core-0.4.1.tar.gz";
636 636 md5 = "01cb19f52bba3e95c9b560f39341f045";
637 637 };
638 638 meta = {
639 639 license = [ pkgs.lib.licenses.bsdOriginal ];
640 640 };
641 641 };
642 dulwich = super.buildPythonPackage {
643 name = "dulwich-0.12.0";
644 buildInputs = with self; [];
645 doCheck = false;
646 propagatedBuildInputs = with self; [];
647 src = fetchurl {
648 url = "https://pypi.python.org/packages/6f/04/fbe561b6d45c0ec758330d5b7f5ba4b6cb4f1ca1ab49859d2fc16320da75/dulwich-0.12.0.tar.gz";
649 md5 = "f3a8a12bd9f9dd8c233e18f3d49436fa";
650 };
651 meta = {
652 license = [ pkgs.lib.licenses.gpl2Plus ];
653 };
654 };
655 642 ecdsa = super.buildPythonPackage {
656 643 name = "ecdsa-0.11";
657 644 buildInputs = with self; [];
658 645 doCheck = false;
659 646 propagatedBuildInputs = with self; [];
660 647 src = fetchurl {
661 648 url = "https://pypi.python.org/packages/6c/3f/92fe5dcdcaa7bd117be21e5520c9a54375112b66ec000d209e9e9519fad1/ecdsa-0.11.tar.gz";
662 649 md5 = "8ef586fe4dbb156697d756900cb41d7c";
663 650 };
664 651 meta = {
665 652 license = [ pkgs.lib.licenses.mit ];
666 653 };
667 654 };
668 655 elasticsearch = super.buildPythonPackage {
669 656 name = "elasticsearch-2.3.0";
670 657 buildInputs = with self; [];
671 658 doCheck = false;
672 659 propagatedBuildInputs = with self; [urllib3];
673 660 src = fetchurl {
674 661 url = "https://pypi.python.org/packages/10/35/5fd52c5f0b0ee405ed4b5195e8bce44c5e041787680dc7b94b8071cac600/elasticsearch-2.3.0.tar.gz";
675 662 md5 = "2550f3b51629cf1ef9636608af92c340";
676 663 };
677 664 meta = {
678 665 license = [ pkgs.lib.licenses.asl20 ];
679 666 };
680 667 };
681 668 elasticsearch-dsl = super.buildPythonPackage {
682 name = "elasticsearch-dsl-2.0.0";
669 name = "elasticsearch-dsl-2.2.0";
683 670 buildInputs = with self; [];
684 671 doCheck = false;
685 672 propagatedBuildInputs = with self; [six python-dateutil elasticsearch];
686 673 src = fetchurl {
687 url = "https://pypi.python.org/packages/4e/5d/e788ae8dbe2ff4d13426db0a027533386a5c276c77a2654dc0e2007ce04a/elasticsearch-dsl-2.0.0.tar.gz";
688 md5 = "4cdfec81bb35383dd3b7d02d7dc5ee68";
674 url = "https://pypi.python.org/packages/66/2f/52a086968788e58461641570f45c3207a52d46ebbe9b77dc22b6a8ffda66/elasticsearch-dsl-2.2.0.tar.gz";
675 md5 = "fa6bd3c87ea3caa8f0f051bc37c53221";
689 676 };
690 677 meta = {
691 678 license = [ pkgs.lib.licenses.asl20 ];
692 679 };
693 680 };
694 681 enum34 = super.buildPythonPackage {
695 682 name = "enum34-1.1.6";
696 683 buildInputs = with self; [];
697 684 doCheck = false;
698 685 propagatedBuildInputs = with self; [];
699 686 src = fetchurl {
700 687 url = "https://pypi.python.org/packages/bf/3e/31d502c25302814a7c2f1d3959d2a3b3f78e509002ba91aea64993936876/enum34-1.1.6.tar.gz";
701 688 md5 = "5f13a0841a61f7fc295c514490d120d0";
702 689 };
703 690 meta = {
704 691 license = [ pkgs.lib.licenses.bsdOriginal ];
705 692 };
706 693 };
707 694 future = super.buildPythonPackage {
708 695 name = "future-0.14.3";
709 696 buildInputs = with self; [];
710 697 doCheck = false;
711 698 propagatedBuildInputs = with self; [];
712 699 src = fetchurl {
713 700 url = "https://pypi.python.org/packages/83/80/8ef3a11a15f8eaafafa0937b20c1b3f73527e69ab6b3fa1cf94a5a96aabb/future-0.14.3.tar.gz";
714 701 md5 = "e94079b0bd1fc054929e8769fc0f6083";
715 702 };
716 703 meta = {
717 704 license = [ { fullName = "OSI Approved"; } pkgs.lib.licenses.mit ];
718 705 };
719 706 };
720 707 futures = super.buildPythonPackage {
721 708 name = "futures-3.0.2";
722 709 buildInputs = with self; [];
723 710 doCheck = false;
724 711 propagatedBuildInputs = with self; [];
725 712 src = fetchurl {
726 713 url = "https://pypi.python.org/packages/f8/e7/fc0fcbeb9193ba2d4de00b065e7fd5aecd0679e93ce95a07322b2b1434f4/futures-3.0.2.tar.gz";
727 714 md5 = "42aaf1e4de48d6e871d77dc1f9d96d5a";
728 715 };
729 716 meta = {
730 717 license = [ pkgs.lib.licenses.bsdOriginal ];
731 718 };
732 719 };
733 720 gevent = super.buildPythonPackage {
734 name = "gevent-1.1.1";
721 name = "gevent-1.1.2";
735 722 buildInputs = with self; [];
736 723 doCheck = false;
737 724 propagatedBuildInputs = with self; [greenlet];
738 725 src = fetchurl {
739 url = "https://pypi.python.org/packages/12/dc/0b2e57823225de86f6e111a65d212c9e3b64847dddaa19691a6cb94b0b2e/gevent-1.1.1.tar.gz";
740 md5 = "1532f5396ab4d07a231f1935483be7c3";
726 url = "https://pypi.python.org/packages/43/8f/cb3224a0e6ab663547f45c10d0651cfd52633fde4283bf68d627084df8cc/gevent-1.1.2.tar.gz";
727 md5 = "bb32a2f852a4997138014d5007215c6e";
741 728 };
742 729 meta = {
743 730 license = [ pkgs.lib.licenses.mit ];
744 731 };
745 732 };
746 733 gnureadline = super.buildPythonPackage {
747 734 name = "gnureadline-6.3.3";
748 735 buildInputs = with self; [];
749 736 doCheck = false;
750 737 propagatedBuildInputs = with self; [];
751 738 src = fetchurl {
752 739 url = "https://pypi.python.org/packages/3a/ee/2c3f568b0a74974791ac590ec742ef6133e2fbd287a074ba72a53fa5e97c/gnureadline-6.3.3.tar.gz";
753 740 md5 = "c4af83c9a3fbeac8f2da9b5a7c60e51c";
754 741 };
755 742 meta = {
756 743 license = [ pkgs.lib.licenses.gpl1 ];
757 744 };
758 745 };
759 746 gprof2dot = super.buildPythonPackage {
760 name = "gprof2dot-2015.12.1";
747 name = "gprof2dot-2016.10.13";
761 748 buildInputs = with self; [];
762 749 doCheck = false;
763 750 propagatedBuildInputs = with self; [];
764 751 src = fetchurl {
765 url = "https://pypi.python.org/packages/b9/34/7bf93c1952d40fa5c95ad963f4d8344b61ef58558632402eca18e6c14127/gprof2dot-2015.12.1.tar.gz";
766 md5 = "e23bf4e2f94db032750c193384b4165b";
752 url = "https://pypi.python.org/packages/a0/e0/73c71baed306f0402a00a94ffc7b2be94ad1296dfcb8b46912655b93154c/gprof2dot-2016.10.13.tar.gz";
753 md5 = "0125401f15fd2afe1df686a76c64a4fd";
767 754 };
768 755 meta = {
769 756 license = [ { fullName = "LGPL"; } ];
770 757 };
771 758 };
772 759 greenlet = super.buildPythonPackage {
773 name = "greenlet-0.4.9";
760 name = "greenlet-0.4.10";
774 761 buildInputs = with self; [];
775 762 doCheck = false;
776 763 propagatedBuildInputs = with self; [];
777 764 src = fetchurl {
778 url = "https://pypi.python.org/packages/4e/3d/9d421539b74e33608b245092870156b2e171fb49f2b51390aa4641eecb4a/greenlet-0.4.9.zip";
779 md5 = "c6659cdb2a5e591723e629d2eef22e82";
765 url = "https://pypi.python.org/packages/67/62/ca2a95648666eaa2ffeb6a9b3964f21d419ae27f82f2e66b53da5b943fc4/greenlet-0.4.10.zip";
766 md5 = "bed0c4b3b896702131f4d5c72f87c41d";
780 767 };
781 768 meta = {
782 769 license = [ pkgs.lib.licenses.mit ];
783 770 };
784 771 };
785 772 gunicorn = super.buildPythonPackage {
786 773 name = "gunicorn-19.6.0";
787 774 buildInputs = with self; [];
788 775 doCheck = false;
789 776 propagatedBuildInputs = with self; [];
790 777 src = fetchurl {
791 778 url = "https://pypi.python.org/packages/84/ce/7ea5396efad1cef682bbc4068e72a0276341d9d9d0f501da609fab9fcb80/gunicorn-19.6.0.tar.gz";
792 779 md5 = "338e5e8a83ea0f0625f768dba4597530";
793 780 };
794 781 meta = {
795 782 license = [ pkgs.lib.licenses.mit ];
796 783 };
797 784 };
798 785 infrae.cache = super.buildPythonPackage {
799 786 name = "infrae.cache-1.0.1";
800 787 buildInputs = with self; [];
801 788 doCheck = false;
802 789 propagatedBuildInputs = with self; [Beaker repoze.lru];
803 790 src = fetchurl {
804 791 url = "https://pypi.python.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz";
805 792 md5 = "b09076a766747e6ed2a755cc62088e32";
806 793 };
807 794 meta = {
808 795 license = [ pkgs.lib.licenses.zpt21 ];
809 796 };
810 797 };
811 798 invoke = super.buildPythonPackage {
812 799 name = "invoke-0.13.0";
813 800 buildInputs = with self; [];
814 801 doCheck = false;
815 802 propagatedBuildInputs = with self; [];
816 803 src = fetchurl {
817 804 url = "https://pypi.python.org/packages/47/bf/d07ef52fa1ac645468858bbac7cb95b246a972a045e821493d17d89c81be/invoke-0.13.0.tar.gz";
818 805 md5 = "c0d1ed4bfb34eaab551662d8cfee6540";
819 806 };
820 807 meta = {
821 808 license = [ pkgs.lib.licenses.bsdOriginal ];
822 809 };
823 810 };
824 811 ipdb = super.buildPythonPackage {
825 812 name = "ipdb-0.10.1";
826 813 buildInputs = with self; [];
827 814 doCheck = false;
828 815 propagatedBuildInputs = with self; [ipython setuptools];
829 816 src = fetchurl {
830 817 url = "https://pypi.python.org/packages/eb/0a/0a37dc19572580336ad3813792c0d18c8d7117c2d66fc63c501f13a7a8f8/ipdb-0.10.1.tar.gz";
831 818 md5 = "4aeab65f633ddc98ebdb5eebf08dc713";
832 819 };
833 820 meta = {
834 821 license = [ pkgs.lib.licenses.bsdOriginal ];
835 822 };
836 823 };
837 824 ipython = super.buildPythonPackage {
838 825 name = "ipython-5.1.0";
839 826 buildInputs = with self; [];
840 827 doCheck = false;
841 828 propagatedBuildInputs = with self; [setuptools decorator pickleshare simplegeneric traitlets prompt-toolkit Pygments pexpect backports.shutil-get-terminal-size pathlib2 pexpect];
842 829 src = fetchurl {
843 830 url = "https://pypi.python.org/packages/89/63/a9292f7cd9d0090a0f995e1167f3f17d5889dcbc9a175261719c513b9848/ipython-5.1.0.tar.gz";
844 831 md5 = "47c8122420f65b58784cb4b9b4af35e3";
845 832 };
846 833 meta = {
847 834 license = [ pkgs.lib.licenses.bsdOriginal ];
848 835 };
849 836 };
850 837 ipython-genutils = super.buildPythonPackage {
851 838 name = "ipython-genutils-0.1.0";
852 839 buildInputs = with self; [];
853 840 doCheck = false;
854 841 propagatedBuildInputs = with self; [];
855 842 src = fetchurl {
856 843 url = "https://pypi.python.org/packages/71/b7/a64c71578521606edbbce15151358598f3dfb72a3431763edc2baf19e71f/ipython_genutils-0.1.0.tar.gz";
857 844 md5 = "9a8afbe0978adbcbfcb3b35b2d015a56";
858 845 };
859 846 meta = {
860 847 license = [ pkgs.lib.licenses.bsdOriginal ];
861 848 };
862 849 };
863 850 iso8601 = super.buildPythonPackage {
864 851 name = "iso8601-0.1.11";
865 852 buildInputs = with self; [];
866 853 doCheck = false;
867 854 propagatedBuildInputs = with self; [];
868 855 src = fetchurl {
869 856 url = "https://pypi.python.org/packages/c0/75/c9209ee4d1b5975eb8c2cba4428bde6b61bd55664a98290dd015cdb18e98/iso8601-0.1.11.tar.gz";
870 857 md5 = "b06d11cd14a64096f907086044f0fe38";
871 858 };
872 859 meta = {
873 860 license = [ pkgs.lib.licenses.mit ];
874 861 };
875 862 };
876 863 itsdangerous = super.buildPythonPackage {
877 864 name = "itsdangerous-0.24";
878 865 buildInputs = with self; [];
879 866 doCheck = false;
880 867 propagatedBuildInputs = with self; [];
881 868 src = fetchurl {
882 869 url = "https://pypi.python.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz";
883 870 md5 = "a3d55aa79369aef5345c036a8a26307f";
884 871 };
885 872 meta = {
886 873 license = [ pkgs.lib.licenses.bsdOriginal ];
887 874 };
888 875 };
889 876 kombu = super.buildPythonPackage {
890 877 name = "kombu-1.5.1";
891 878 buildInputs = with self; [];
892 879 doCheck = false;
893 880 propagatedBuildInputs = with self; [anyjson amqplib];
894 881 src = fetchurl {
895 882 url = "https://pypi.python.org/packages/19/53/74bf2a624644b45f0850a638752514fc10a8e1cbd738f10804951a6df3f5/kombu-1.5.1.tar.gz";
896 883 md5 = "50662f3c7e9395b3d0721fb75d100b63";
897 884 };
898 885 meta = {
899 886 license = [ pkgs.lib.licenses.bsdOriginal ];
900 887 };
901 888 };
902 889 lxml = super.buildPythonPackage {
903 890 name = "lxml-3.4.4";
904 891 buildInputs = with self; [];
905 892 doCheck = false;
906 893 propagatedBuildInputs = with self; [];
907 894 src = fetchurl {
908 895 url = "https://pypi.python.org/packages/63/c7/4f2a2a4ad6c6fa99b14be6b3c1cece9142e2d915aa7c43c908677afc8fa4/lxml-3.4.4.tar.gz";
909 896 md5 = "a9a65972afc173ec7a39c585f4eea69c";
910 897 };
911 898 meta = {
912 899 license = [ pkgs.lib.licenses.bsdOriginal ];
913 900 };
914 901 };
915 902 meld3 = super.buildPythonPackage {
916 903 name = "meld3-1.0.2";
917 904 buildInputs = with self; [];
918 905 doCheck = false;
919 906 propagatedBuildInputs = with self; [];
920 907 src = fetchurl {
921 908 url = "https://pypi.python.org/packages/45/a0/317c6422b26c12fe0161e936fc35f36552069ba8e6f7ecbd99bbffe32a5f/meld3-1.0.2.tar.gz";
922 909 md5 = "3ccc78cd79cffd63a751ad7684c02c91";
923 910 };
924 911 meta = {
925 912 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
926 913 };
927 914 };
928 915 mock = super.buildPythonPackage {
929 916 name = "mock-1.0.1";
930 917 buildInputs = with self; [];
931 918 doCheck = false;
932 919 propagatedBuildInputs = with self; [];
933 920 src = fetchurl {
934 921 url = "https://pypi.python.org/packages/15/45/30273ee91feb60dabb8fbb2da7868520525f02cf910279b3047182feed80/mock-1.0.1.zip";
935 922 md5 = "869f08d003c289a97c1a6610faf5e913";
936 923 };
937 924 meta = {
938 925 license = [ pkgs.lib.licenses.bsdOriginal ];
939 926 };
940 927 };
941 928 msgpack-python = super.buildPythonPackage {
942 name = "msgpack-python-0.4.6";
929 name = "msgpack-python-0.4.8";
943 930 buildInputs = with self; [];
944 931 doCheck = false;
945 932 propagatedBuildInputs = with self; [];
946 933 src = fetchurl {
947 url = "https://pypi.python.org/packages/15/ce/ff2840885789ef8035f66cd506ea05bdb228340307d5e71a7b1e3f82224c/msgpack-python-0.4.6.tar.gz";
948 md5 = "8b317669314cf1bc881716cccdaccb30";
934 url = "https://pypi.python.org/packages/21/27/8a1d82041c7a2a51fcc73675875a5f9ea06c2663e02fcfeb708be1d081a0/msgpack-python-0.4.8.tar.gz";
935 md5 = "dcd854fb41ee7584ebbf35e049e6be98";
949 936 };
950 937 meta = {
951 938 license = [ pkgs.lib.licenses.asl20 ];
952 939 };
953 940 };
954 941 nose = super.buildPythonPackage {
955 942 name = "nose-1.3.6";
956 943 buildInputs = with self; [];
957 944 doCheck = false;
958 945 propagatedBuildInputs = with self; [];
959 946 src = fetchurl {
960 947 url = "https://pypi.python.org/packages/70/c7/469e68148d17a0d3db5ed49150242fd70a74a8147b8f3f8b87776e028d99/nose-1.3.6.tar.gz";
961 948 md5 = "0ca546d81ca8309080fc80cb389e7a16";
962 949 };
963 950 meta = {
964 951 license = [ { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "GNU LGPL"; } ];
965 952 };
966 953 };
967 954 objgraph = super.buildPythonPackage {
968 955 name = "objgraph-2.0.0";
969 956 buildInputs = with self; [];
970 957 doCheck = false;
971 958 propagatedBuildInputs = with self; [];
972 959 src = fetchurl {
973 960 url = "https://pypi.python.org/packages/d7/33/ace750b59247496ed769b170586c5def7202683f3d98e737b75b767ff29e/objgraph-2.0.0.tar.gz";
974 961 md5 = "25b0d5e5adc74aa63ead15699614159c";
975 962 };
976 963 meta = {
977 964 license = [ pkgs.lib.licenses.mit ];
978 965 };
979 966 };
980 967 packaging = super.buildPythonPackage {
981 968 name = "packaging-15.2";
982 969 buildInputs = with self; [];
983 970 doCheck = false;
984 971 propagatedBuildInputs = with self; [];
985 972 src = fetchurl {
986 973 url = "https://pypi.python.org/packages/24/c4/185da1304f07047dc9e0c46c31db75c0351bd73458ac3efad7da3dbcfbe1/packaging-15.2.tar.gz";
987 974 md5 = "c16093476f6ced42128bf610e5db3784";
988 975 };
989 976 meta = {
990 977 license = [ pkgs.lib.licenses.asl20 ];
991 978 };
992 979 };
993 980 paramiko = super.buildPythonPackage {
994 981 name = "paramiko-1.15.1";
995 982 buildInputs = with self; [];
996 983 doCheck = false;
997 984 propagatedBuildInputs = with self; [pycrypto ecdsa];
998 985 src = fetchurl {
999 986 url = "https://pypi.python.org/packages/04/2b/a22d2a560c1951abbbf95a0628e245945565f70dc082d9e784666887222c/paramiko-1.15.1.tar.gz";
1000 987 md5 = "48c274c3f9b1282932567b21f6acf3b5";
1001 988 };
1002 989 meta = {
1003 990 license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1004 991 };
1005 992 };
1006 993 pathlib2 = super.buildPythonPackage {
1007 994 name = "pathlib2-2.1.0";
1008 995 buildInputs = with self; [];
1009 996 doCheck = false;
1010 997 propagatedBuildInputs = with self; [six];
1011 998 src = fetchurl {
1012 999 url = "https://pypi.python.org/packages/c9/27/8448b10d8440c08efeff0794adf7d0ed27adb98372c70c7b38f3947d4749/pathlib2-2.1.0.tar.gz";
1013 1000 md5 = "38e4f58b4d69dfcb9edb49a54a8b28d2";
1014 1001 };
1015 1002 meta = {
1016 1003 license = [ pkgs.lib.licenses.mit ];
1017 1004 };
1018 1005 };
1019 1006 peppercorn = super.buildPythonPackage {
1020 1007 name = "peppercorn-0.5";
1021 1008 buildInputs = with self; [];
1022 1009 doCheck = false;
1023 1010 propagatedBuildInputs = with self; [];
1024 1011 src = fetchurl {
1025 1012 url = "https://pypi.python.org/packages/45/ec/a62ec317d1324a01567c5221b420742f094f05ee48097e5157d32be3755c/peppercorn-0.5.tar.gz";
1026 1013 md5 = "f08efbca5790019ab45d76b7244abd40";
1027 1014 };
1028 1015 meta = {
1029 1016 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1030 1017 };
1031 1018 };
1032 1019 pexpect = super.buildPythonPackage {
1033 1020 name = "pexpect-4.2.1";
1034 1021 buildInputs = with self; [];
1035 1022 doCheck = false;
1036 1023 propagatedBuildInputs = with self; [ptyprocess];
1037 1024 src = fetchurl {
1038 1025 url = "https://pypi.python.org/packages/e8/13/d0b0599099d6cd23663043a2a0bb7c61e58c6ba359b2656e6fb000ef5b98/pexpect-4.2.1.tar.gz";
1039 1026 md5 = "3694410001a99dff83f0b500a1ca1c95";
1040 1027 };
1041 1028 meta = {
1042 1029 license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
1043 1030 };
1044 1031 };
1045 1032 pickleshare = super.buildPythonPackage {
1046 1033 name = "pickleshare-0.7.4";
1047 1034 buildInputs = with self; [];
1048 1035 doCheck = false;
1049 1036 propagatedBuildInputs = with self; [pathlib2];
1050 1037 src = fetchurl {
1051 1038 url = "https://pypi.python.org/packages/69/fe/dd137d84daa0fd13a709e448138e310d9ea93070620c9db5454e234af525/pickleshare-0.7.4.tar.gz";
1052 1039 md5 = "6a9e5dd8dfc023031f6b7b3f824cab12";
1053 1040 };
1054 1041 meta = {
1055 1042 license = [ pkgs.lib.licenses.mit ];
1056 1043 };
1057 1044 };
1058 1045 prompt-toolkit = super.buildPythonPackage {
1059 1046 name = "prompt-toolkit-1.0.9";
1060 1047 buildInputs = with self; [];
1061 1048 doCheck = false;
1062 1049 propagatedBuildInputs = with self; [six wcwidth];
1063 1050 src = fetchurl {
1064 1051 url = "https://pypi.python.org/packages/83/14/5ac258da6c530eca02852ee25c7a9ff3ca78287bb4c198d0d0055845d856/prompt_toolkit-1.0.9.tar.gz";
1065 1052 md5 = "a39f91a54308fb7446b1a421c11f227c";
1066 1053 };
1067 1054 meta = {
1068 1055 license = [ pkgs.lib.licenses.bsdOriginal ];
1069 1056 };
1070 1057 };
1071 1058 psutil = super.buildPythonPackage {
1072 1059 name = "psutil-4.3.1";
1073 1060 buildInputs = with self; [];
1074 1061 doCheck = false;
1075 1062 propagatedBuildInputs = with self; [];
1076 1063 src = fetchurl {
1077 1064 url = "https://pypi.python.org/packages/78/cc/f267a1371f229bf16db6a4e604428c3b032b823b83155bd33cef45e49a53/psutil-4.3.1.tar.gz";
1078 1065 md5 = "199a366dba829c88bddaf5b41d19ddc0";
1079 1066 };
1080 1067 meta = {
1081 1068 license = [ pkgs.lib.licenses.bsdOriginal ];
1082 1069 };
1083 1070 };
1084 1071 psycopg2 = super.buildPythonPackage {
1085 1072 name = "psycopg2-2.6.1";
1086 1073 buildInputs = with self; [];
1087 1074 doCheck = false;
1088 1075 propagatedBuildInputs = with self; [];
1089 1076 src = fetchurl {
1090 1077 url = "https://pypi.python.org/packages/86/fd/cc8315be63a41fe000cce20482a917e874cdc1151e62cb0141f5e55f711e/psycopg2-2.6.1.tar.gz";
1091 1078 md5 = "842b44f8c95517ed5b792081a2370da1";
1092 1079 };
1093 1080 meta = {
1094 1081 license = [ pkgs.lib.licenses.zpt21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
1095 1082 };
1096 1083 };
1097 1084 ptyprocess = super.buildPythonPackage {
1098 1085 name = "ptyprocess-0.5.1";
1099 1086 buildInputs = with self; [];
1100 1087 doCheck = false;
1101 1088 propagatedBuildInputs = with self; [];
1102 1089 src = fetchurl {
1103 1090 url = "https://pypi.python.org/packages/db/d7/b465161910f3d1cef593c5e002bff67e0384898f597f1a7fdc8db4c02bf6/ptyprocess-0.5.1.tar.gz";
1104 1091 md5 = "94e537122914cc9ec9c1eadcd36e73a1";
1105 1092 };
1106 1093 meta = {
1107 1094 license = [ ];
1108 1095 };
1109 1096 };
1110 1097 py = super.buildPythonPackage {
1111 name = "py-1.4.29";
1098 name = "py-1.4.31";
1112 1099 buildInputs = with self; [];
1113 1100 doCheck = false;
1114 1101 propagatedBuildInputs = with self; [];
1115 1102 src = fetchurl {
1116 url = "https://pypi.python.org/packages/2a/bc/a1a4a332ac10069b8e5e25136a35e08a03f01fd6ab03d819889d79a1fd65/py-1.4.29.tar.gz";
1117 md5 = "c28e0accba523a29b35a48bb703fb96c";
1103 url = "https://pypi.python.org/packages/f4/9a/8dfda23f36600dd701c6722316ba8a3ab4b990261f83e7d3ffc6dfedf7ef/py-1.4.31.tar.gz";
1104 md5 = "5d2c63c56dc3f2115ec35c066ecd582b";
1118 1105 };
1119 1106 meta = {
1120 1107 license = [ pkgs.lib.licenses.mit ];
1121 1108 };
1122 1109 };
1123 1110 py-bcrypt = super.buildPythonPackage {
1124 1111 name = "py-bcrypt-0.4";
1125 1112 buildInputs = with self; [];
1126 1113 doCheck = false;
1127 1114 propagatedBuildInputs = with self; [];
1128 1115 src = fetchurl {
1129 1116 url = "https://pypi.python.org/packages/68/b1/1c3068c5c4d2e35c48b38dcc865301ebfdf45f54507086ac65ced1fd3b3d/py-bcrypt-0.4.tar.gz";
1130 1117 md5 = "dd8b367d6b716a2ea2e72392525f4e36";
1131 1118 };
1132 1119 meta = {
1133 1120 license = [ pkgs.lib.licenses.bsdOriginal ];
1134 1121 };
1135 1122 };
1136 1123 py-gfm = super.buildPythonPackage {
1137 1124 name = "py-gfm-0.1.3";
1138 1125 buildInputs = with self; [];
1139 1126 doCheck = false;
1140 1127 propagatedBuildInputs = with self; [setuptools Markdown];
1141 1128 src = fetchurl {
1142 url = "https://pypi.python.org/packages/12/e4/6b3d8678da04f97d7490d8264d8de51c2dc9fb91209ccee9c515c95e14c5/py-gfm-0.1.3.tar.gz";
1143 md5 = "e588d9e69640a241b97e2c59c22527a6";
1129 url = "https://code.rhodecode.com/upstream/py-gfm/archive/0d66a19bc16e3d49de273c0f797d4e4781e8c0f2.tar.gz?md5=0d0d5385bfb629eea636a80b9c2bfd16";
1130 md5 = "0d0d5385bfb629eea636a80b9c2bfd16";
1144 1131 };
1145 1132 meta = {
1146 1133 license = [ pkgs.lib.licenses.bsdOriginal ];
1147 1134 };
1148 1135 };
1149 1136 pycrypto = super.buildPythonPackage {
1150 1137 name = "pycrypto-2.6.1";
1151 1138 buildInputs = with self; [];
1152 1139 doCheck = false;
1153 1140 propagatedBuildInputs = with self; [];
1154 1141 src = fetchurl {
1155 1142 url = "https://pypi.python.org/packages/60/db/645aa9af249f059cc3a368b118de33889219e0362141e75d4eaf6f80f163/pycrypto-2.6.1.tar.gz";
1156 1143 md5 = "55a61a054aa66812daf5161a0d5d7eda";
1157 1144 };
1158 1145 meta = {
1159 1146 license = [ pkgs.lib.licenses.publicDomain ];
1160 1147 };
1161 1148 };
1162 1149 pycurl = super.buildPythonPackage {
1163 1150 name = "pycurl-7.19.5";
1164 1151 buildInputs = with self; [];
1165 1152 doCheck = false;
1166 1153 propagatedBuildInputs = with self; [];
1167 1154 src = fetchurl {
1168 1155 url = "https://pypi.python.org/packages/6c/48/13bad289ef6f4869b1d8fc11ae54de8cfb3cc4a2eb9f7419c506f763be46/pycurl-7.19.5.tar.gz";
1169 1156 md5 = "47b4eac84118e2606658122104e62072";
1170 1157 };
1171 1158 meta = {
1172 1159 license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1173 1160 };
1174 1161 };
1175 1162 pyflakes = super.buildPythonPackage {
1176 1163 name = "pyflakes-0.8.1";
1177 1164 buildInputs = with self; [];
1178 1165 doCheck = false;
1179 1166 propagatedBuildInputs = with self; [];
1180 1167 src = fetchurl {
1181 1168 url = "https://pypi.python.org/packages/75/22/a90ec0252f4f87f3ffb6336504de71fe16a49d69c4538dae2f12b9360a38/pyflakes-0.8.1.tar.gz";
1182 1169 md5 = "905fe91ad14b912807e8fdc2ac2e2c23";
1183 1170 };
1184 1171 meta = {
1185 1172 license = [ pkgs.lib.licenses.mit ];
1186 1173 };
1187 1174 };
1188 1175 pygments-markdown-lexer = super.buildPythonPackage {
1189 1176 name = "pygments-markdown-lexer-0.1.0.dev39";
1190 1177 buildInputs = with self; [];
1191 1178 doCheck = false;
1192 1179 propagatedBuildInputs = with self; [Pygments];
1193 1180 src = fetchurl {
1194 1181 url = "https://pypi.python.org/packages/c3/12/674cdee66635d638cedb2c5d9c85ce507b7b2f91bdba29e482f1b1160ff6/pygments-markdown-lexer-0.1.0.dev39.zip";
1195 1182 md5 = "6360fe0f6d1f896e35b7a0142ce6459c";
1196 1183 };
1197 1184 meta = {
1198 1185 license = [ pkgs.lib.licenses.asl20 ];
1199 1186 };
1200 1187 };
1201 1188 pyparsing = super.buildPythonPackage {
1202 1189 name = "pyparsing-1.5.7";
1203 1190 buildInputs = with self; [];
1204 1191 doCheck = false;
1205 1192 propagatedBuildInputs = with self; [];
1206 1193 src = fetchurl {
1207 1194 url = "https://pypi.python.org/packages/2e/26/e8fb5b4256a5f5036be7ce115ef8db8d06bc537becfbdc46c6af008314ee/pyparsing-1.5.7.zip";
1208 1195 md5 = "b86854857a368d6ccb4d5b6e76d0637f";
1209 1196 };
1210 1197 meta = {
1211 1198 license = [ pkgs.lib.licenses.mit ];
1212 1199 };
1213 1200 };
1214 1201 pyramid = super.buildPythonPackage {
1215 1202 name = "pyramid-1.6.1";
1216 1203 buildInputs = with self; [];
1217 1204 doCheck = false;
1218 1205 propagatedBuildInputs = with self; [setuptools WebOb repoze.lru zope.interface zope.deprecation venusian translationstring PasteDeploy];
1219 1206 src = fetchurl {
1220 1207 url = "https://pypi.python.org/packages/30/b3/fcc4a2a4800cbf21989e00454b5828cf1f7fe35c63e0810b350e56d4c475/pyramid-1.6.1.tar.gz";
1221 1208 md5 = "b18688ff3cc33efdbb098a35b45dd122";
1222 1209 };
1223 1210 meta = {
1224 1211 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1225 1212 };
1226 1213 };
1227 1214 pyramid-beaker = super.buildPythonPackage {
1228 1215 name = "pyramid-beaker-0.8";
1229 1216 buildInputs = with self; [];
1230 1217 doCheck = false;
1231 1218 propagatedBuildInputs = with self; [pyramid Beaker];
1232 1219 src = fetchurl {
1233 1220 url = "https://pypi.python.org/packages/d9/6e/b85426e00fd3d57f4545f74e1c3828552d8700f13ededeef9233f7bca8be/pyramid_beaker-0.8.tar.gz";
1234 1221 md5 = "22f14be31b06549f80890e2c63a93834";
1235 1222 };
1236 1223 meta = {
1237 1224 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1238 1225 };
1239 1226 };
1240 1227 pyramid-debugtoolbar = super.buildPythonPackage {
1241 1228 name = "pyramid-debugtoolbar-2.4.2";
1242 1229 buildInputs = with self; [];
1243 1230 doCheck = false;
1244 1231 propagatedBuildInputs = with self; [pyramid pyramid-mako repoze.lru Pygments];
1245 1232 src = fetchurl {
1246 1233 url = "https://pypi.python.org/packages/89/00/ed5426ee41ed747ba3ffd30e8230841a6878286ea67d480b1444d24f06a2/pyramid_debugtoolbar-2.4.2.tar.gz";
1247 1234 md5 = "073ea67086cc4bd5decc3a000853642d";
1248 1235 };
1249 1236 meta = {
1250 1237 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
1251 1238 };
1252 1239 };
1253 1240 pyramid-jinja2 = super.buildPythonPackage {
1254 1241 name = "pyramid-jinja2-2.5";
1255 1242 buildInputs = with self; [];
1256 1243 doCheck = false;
1257 1244 propagatedBuildInputs = with self; [pyramid zope.deprecation Jinja2 MarkupSafe];
1258 1245 src = fetchurl {
1259 1246 url = "https://pypi.python.org/packages/a1/80/595e26ffab7deba7208676b6936b7e5a721875710f982e59899013cae1ed/pyramid_jinja2-2.5.tar.gz";
1260 1247 md5 = "07cb6547204ac5e6f0b22a954ccee928";
1261 1248 };
1262 1249 meta = {
1263 1250 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1264 1251 };
1265 1252 };
1266 1253 pyramid-mako = super.buildPythonPackage {
1267 1254 name = "pyramid-mako-1.0.2";
1268 1255 buildInputs = with self; [];
1269 1256 doCheck = false;
1270 1257 propagatedBuildInputs = with self; [pyramid Mako];
1271 1258 src = fetchurl {
1272 1259 url = "https://pypi.python.org/packages/f1/92/7e69bcf09676d286a71cb3bbb887b16595b96f9ba7adbdc239ffdd4b1eb9/pyramid_mako-1.0.2.tar.gz";
1273 1260 md5 = "ee25343a97eb76bd90abdc2a774eb48a";
1274 1261 };
1275 1262 meta = {
1276 1263 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1277 1264 };
1278 1265 };
1279 1266 pysqlite = super.buildPythonPackage {
1280 1267 name = "pysqlite-2.6.3";
1281 1268 buildInputs = with self; [];
1282 1269 doCheck = false;
1283 1270 propagatedBuildInputs = with self; [];
1284 1271 src = fetchurl {
1285 1272 url = "https://pypi.python.org/packages/5c/a6/1c429cd4c8069cf4bfbd0eb4d592b3f4042155a8202df83d7e9b93aa3dc2/pysqlite-2.6.3.tar.gz";
1286 1273 md5 = "7ff1cedee74646b50117acff87aa1cfa";
1287 1274 };
1288 1275 meta = {
1289 1276 license = [ { fullName = "zlib/libpng License"; } { fullName = "zlib/libpng license"; } ];
1290 1277 };
1291 1278 };
1292 1279 pytest = super.buildPythonPackage {
1293 name = "pytest-2.8.5";
1280 name = "pytest-3.0.5";
1294 1281 buildInputs = with self; [];
1295 1282 doCheck = false;
1296 1283 propagatedBuildInputs = with self; [py];
1297 1284 src = fetchurl {
1298 url = "https://pypi.python.org/packages/b1/3d/d7ea9b0c51e0cacded856e49859f0a13452747491e842c236bbab3714afe/pytest-2.8.5.zip";
1299 md5 = "8493b06f700862f1294298d6c1b715a9";
1285 url = "https://pypi.python.org/packages/a8/87/b7ca49efe52d2b4169f2bfc49aa5e384173c4619ea8e635f123a0dac5b75/pytest-3.0.5.tar.gz";
1286 md5 = "cefd527b59332688bf5db4a10aa8a7cb";
1300 1287 };
1301 1288 meta = {
1302 1289 license = [ pkgs.lib.licenses.mit ];
1303 1290 };
1304 1291 };
1305 1292 pytest-catchlog = super.buildPythonPackage {
1306 1293 name = "pytest-catchlog-1.2.2";
1307 1294 buildInputs = with self; [];
1308 1295 doCheck = false;
1309 1296 propagatedBuildInputs = with self; [py pytest];
1310 1297 src = fetchurl {
1311 1298 url = "https://pypi.python.org/packages/f2/2b/2faccdb1a978fab9dd0bf31cca9f6847fbe9184a0bdcc3011ac41dd44191/pytest-catchlog-1.2.2.zip";
1312 1299 md5 = "09d890c54c7456c818102b7ff8c182c8";
1313 1300 };
1314 1301 meta = {
1315 1302 license = [ pkgs.lib.licenses.mit ];
1316 1303 };
1317 1304 };
1318 1305 pytest-cov = super.buildPythonPackage {
1319 name = "pytest-cov-1.8.1";
1306 name = "pytest-cov-2.4.0";
1320 1307 buildInputs = with self; [];
1321 1308 doCheck = false;
1322 propagatedBuildInputs = with self; [py pytest coverage cov-core];
1309 propagatedBuildInputs = with self; [pytest coverage];
1323 1310 src = fetchurl {
1324 url = "https://pypi.python.org/packages/11/4b/b04646e97f1721878eb21e9f779102d84dd044d324382263b1770a3e4838/pytest-cov-1.8.1.tar.gz";
1325 md5 = "76c778afa2494088270348be42d759fc";
1311 url = "https://pypi.python.org/packages/00/c0/2bfd1fcdb9d407b8ac8185b1cb5ff458105c6b207a9a7f0e13032de9828f/pytest-cov-2.4.0.tar.gz";
1312 md5 = "2fda09677d232acc99ec1b3c5831e33f";
1326 1313 };
1327 1314 meta = {
1328 license = [ pkgs.lib.licenses.mit ];
1315 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.mit ];
1329 1316 };
1330 1317 };
1331 1318 pytest-profiling = super.buildPythonPackage {
1332 name = "pytest-profiling-1.0.1";
1319 name = "pytest-profiling-1.2.2";
1333 1320 buildInputs = with self; [];
1334 1321 doCheck = false;
1335 1322 propagatedBuildInputs = with self; [six pytest gprof2dot];
1336 1323 src = fetchurl {
1337 url = "https://pypi.python.org/packages/d8/67/8ffab73406e22870e07fa4dc8dce1d7689b26dba8efd00161c9b6fc01ec0/pytest-profiling-1.0.1.tar.gz";
1338 md5 = "354404eb5b3fd4dc5eb7fffbb3d9b68b";
1324 url = "https://pypi.python.org/packages/73/e8/804681323bac0bc45c520ec34185ba8469008942266d0074699b204835c1/pytest-profiling-1.2.2.tar.gz";
1325 md5 = "0a16d7dda2d23b91e9730fa4558cf728";
1339 1326 };
1340 1327 meta = {
1341 1328 license = [ pkgs.lib.licenses.mit ];
1342 1329 };
1343 1330 };
1344 1331 pytest-runner = super.buildPythonPackage {
1345 name = "pytest-runner-2.7.1";
1332 name = "pytest-runner-2.9";
1346 1333 buildInputs = with self; [];
1347 1334 doCheck = false;
1348 1335 propagatedBuildInputs = with self; [];
1349 1336 src = fetchurl {
1350 url = "https://pypi.python.org/packages/99/6b/c4ff4418d3424d4475b7af60724fd4a5cdd91ed8e489dc9443281f0052bc/pytest-runner-2.7.1.tar.gz";
1351 md5 = "e56f0bc8d79a6bd91772b44ef4215c7e";
1337 url = "https://pypi.python.org/packages/11/d4/c335ddf94463e451109e3494e909765c3e5205787b772e3b25ee8601b86a/pytest-runner-2.9.tar.gz";
1338 md5 = "2212a2e34404b0960b2fdc2c469247b2";
1352 1339 };
1353 1340 meta = {
1354 1341 license = [ pkgs.lib.licenses.mit ];
1355 1342 };
1356 1343 };
1344 pytest-sugar = super.buildPythonPackage {
1345 name = "pytest-sugar-0.7.1";
1346 buildInputs = with self; [];
1347 doCheck = false;
1348 propagatedBuildInputs = with self; [pytest termcolor];
1349 src = fetchurl {
1350 url = "https://pypi.python.org/packages/03/97/05d988b4fa870e7373e8ee4582408543b9ca2bd35c3c67b569369c6f9c49/pytest-sugar-0.7.1.tar.gz";
1351 md5 = "7400f7c11f3d572b2c2a3b60352d35fe";
1352 };
1353 meta = {
1354 license = [ pkgs.lib.licenses.bsdOriginal ];
1355 };
1356 };
1357 1357 pytest-timeout = super.buildPythonPackage {
1358 name = "pytest-timeout-0.4";
1358 name = "pytest-timeout-1.2.0";
1359 1359 buildInputs = with self; [];
1360 1360 doCheck = false;
1361 1361 propagatedBuildInputs = with self; [pytest];
1362 1362 src = fetchurl {
1363 url = "https://pypi.python.org/packages/24/48/5f6bd4b8026a26e1dd427243d560a29a0f1b24a5c7cffca4bf049a7bb65b/pytest-timeout-0.4.tar.gz";
1364 md5 = "03b28aff69cbbfb959ed35ade5fde262";
1363 url = "https://pypi.python.org/packages/cc/b7/b2a61365ea6b6d2e8881360ae7ed8dad0327ad2df89f2f0be4a02304deb2/pytest-timeout-1.2.0.tar.gz";
1364 md5 = "83607d91aa163562c7ee835da57d061d";
1365 1365 };
1366 1366 meta = {
1367 1367 license = [ pkgs.lib.licenses.mit { fullName = "DFSG approved"; } ];
1368 1368 };
1369 1369 };
1370 1370 python-dateutil = super.buildPythonPackage {
1371 1371 name = "python-dateutil-1.5";
1372 1372 buildInputs = with self; [];
1373 1373 doCheck = false;
1374 1374 propagatedBuildInputs = with self; [];
1375 1375 src = fetchurl {
1376 1376 url = "https://pypi.python.org/packages/b4/7c/df59c89a753eb33c7c44e1dd42de0e9bc2ccdd5a4d576e0bfad97cc280cb/python-dateutil-1.5.tar.gz";
1377 1377 md5 = "0dcb1de5e5cad69490a3b6ab63f0cfa5";
1378 1378 };
1379 1379 meta = {
1380 1380 license = [ pkgs.lib.licenses.psfl ];
1381 1381 };
1382 1382 };
1383 1383 python-editor = super.buildPythonPackage {
1384 1384 name = "python-editor-1.0.3";
1385 1385 buildInputs = with self; [];
1386 1386 doCheck = false;
1387 1387 propagatedBuildInputs = with self; [];
1388 1388 src = fetchurl {
1389 1389 url = "https://pypi.python.org/packages/65/1e/adf6e000ea5dc909aa420352d6ba37f16434c8a3c2fa030445411a1ed545/python-editor-1.0.3.tar.gz";
1390 1390 md5 = "0aca5f2ef176ce68e98a5b7e31372835";
1391 1391 };
1392 1392 meta = {
1393 1393 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
1394 1394 };
1395 1395 };
1396 1396 python-ldap = super.buildPythonPackage {
1397 1397 name = "python-ldap-2.4.19";
1398 1398 buildInputs = with self; [];
1399 1399 doCheck = false;
1400 1400 propagatedBuildInputs = with self; [setuptools];
1401 1401 src = fetchurl {
1402 1402 url = "https://pypi.python.org/packages/42/81/1b64838c82e64f14d4e246ff00b52e650a35c012551b891ada2b85d40737/python-ldap-2.4.19.tar.gz";
1403 1403 md5 = "b941bf31d09739492aa19ef679e94ae3";
1404 1404 };
1405 1405 meta = {
1406 1406 license = [ pkgs.lib.licenses.psfl ];
1407 1407 };
1408 1408 };
1409 1409 python-memcached = super.buildPythonPackage {
1410 1410 name = "python-memcached-1.57";
1411 1411 buildInputs = with self; [];
1412 1412 doCheck = false;
1413 1413 propagatedBuildInputs = with self; [six];
1414 1414 src = fetchurl {
1415 1415 url = "https://pypi.python.org/packages/52/9d/eebc0dcbc5c7c66840ad207dfc1baa376dadb74912484bff73819cce01e6/python-memcached-1.57.tar.gz";
1416 1416 md5 = "de21f64b42b2d961f3d4ad7beb5468a1";
1417 1417 };
1418 1418 meta = {
1419 1419 license = [ pkgs.lib.licenses.psfl ];
1420 1420 };
1421 1421 };
1422 1422 python-pam = super.buildPythonPackage {
1423 1423 name = "python-pam-1.8.2";
1424 1424 buildInputs = with self; [];
1425 1425 doCheck = false;
1426 1426 propagatedBuildInputs = with self; [];
1427 1427 src = fetchurl {
1428 1428 url = "https://pypi.python.org/packages/de/8c/f8f5d38b4f26893af267ea0b39023d4951705ab0413a39e0cf7cf4900505/python-pam-1.8.2.tar.gz";
1429 1429 md5 = "db71b6b999246fb05d78ecfbe166629d";
1430 1430 };
1431 1431 meta = {
1432 1432 license = [ { fullName = "License :: OSI Approved :: MIT License"; } pkgs.lib.licenses.mit ];
1433 1433 };
1434 1434 };
1435 1435 pytz = super.buildPythonPackage {
1436 1436 name = "pytz-2015.4";
1437 1437 buildInputs = with self; [];
1438 1438 doCheck = false;
1439 1439 propagatedBuildInputs = with self; [];
1440 1440 src = fetchurl {
1441 1441 url = "https://pypi.python.org/packages/7e/1a/f43b5c92df7b156822030fed151327ea096bcf417e45acc23bd1df43472f/pytz-2015.4.zip";
1442 1442 md5 = "233f2a2b370d03f9b5911700cc9ebf3c";
1443 1443 };
1444 1444 meta = {
1445 1445 license = [ pkgs.lib.licenses.mit ];
1446 1446 };
1447 1447 };
1448 1448 pyzmq = super.buildPythonPackage {
1449 1449 name = "pyzmq-14.6.0";
1450 1450 buildInputs = with self; [];
1451 1451 doCheck = false;
1452 1452 propagatedBuildInputs = with self; [];
1453 1453 src = fetchurl {
1454 1454 url = "https://pypi.python.org/packages/8a/3b/5463d5a9d712cd8bbdac335daece0d69f6a6792da4e3dd89956c0db4e4e6/pyzmq-14.6.0.tar.gz";
1455 1455 md5 = "395b5de95a931afa5b14c9349a5b8024";
1456 1456 };
1457 1457 meta = {
1458 1458 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1459 1459 };
1460 1460 };
1461 1461 recaptcha-client = super.buildPythonPackage {
1462 1462 name = "recaptcha-client-1.0.6";
1463 1463 buildInputs = with self; [];
1464 1464 doCheck = false;
1465 1465 propagatedBuildInputs = with self; [];
1466 1466 src = fetchurl {
1467 1467 url = "https://pypi.python.org/packages/0a/ea/5f2fbbfd894bdac1c68ef8d92019066cfcf9fbff5fe3d728d2b5c25c8db4/recaptcha-client-1.0.6.tar.gz";
1468 1468 md5 = "74228180f7e1fb76c4d7089160b0d919";
1469 1469 };
1470 1470 meta = {
1471 1471 license = [ { fullName = "MIT/X11"; } ];
1472 1472 };
1473 1473 };
1474 1474 repoze.lru = super.buildPythonPackage {
1475 1475 name = "repoze.lru-0.6";
1476 1476 buildInputs = with self; [];
1477 1477 doCheck = false;
1478 1478 propagatedBuildInputs = with self; [];
1479 1479 src = fetchurl {
1480 1480 url = "https://pypi.python.org/packages/6e/1e/aa15cc90217e086dc8769872c8778b409812ff036bf021b15795638939e4/repoze.lru-0.6.tar.gz";
1481 1481 md5 = "2c3b64b17a8e18b405f55d46173e14dd";
1482 1482 };
1483 1483 meta = {
1484 1484 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1485 1485 };
1486 1486 };
1487 1487 requests = super.buildPythonPackage {
1488 1488 name = "requests-2.9.1";
1489 1489 buildInputs = with self; [];
1490 1490 doCheck = false;
1491 1491 propagatedBuildInputs = with self; [];
1492 1492 src = fetchurl {
1493 1493 url = "https://pypi.python.org/packages/f9/6d/07c44fb1ebe04d069459a189e7dab9e4abfe9432adcd4477367c25332748/requests-2.9.1.tar.gz";
1494 1494 md5 = "0b7f480d19012ec52bab78292efd976d";
1495 1495 };
1496 1496 meta = {
1497 1497 license = [ pkgs.lib.licenses.asl20 ];
1498 1498 };
1499 1499 };
1500 1500 rhodecode-enterprise-ce = super.buildPythonPackage {
1501 name = "rhodecode-enterprise-ce-4.5.2";
1502 buildInputs = with self; [WebTest configobj cssselect lxml mock pytest pytest-cov pytest-runner pytest-sugar];
1501 name = "rhodecode-enterprise-ce-4.6.0";
1502 buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock WebTest cov-core coverage cssselect lxml configobj];
1503 1503 doCheck = true;
1504 1504 propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments pygments-markdown-lexer Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery channelstream colander decorator deform docutils gevent gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson subprocess32 waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt];
1505 1505 src = ./.;
1506 1506 meta = {
1507 license = [ { fullName = "AGPLv3, and Commercial License"; } ];
1507 license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
1508 1508 };
1509 1509 };
1510 1510 rhodecode-tools = super.buildPythonPackage {
1511 name = "rhodecode-tools-0.10.2";
1511 name = "rhodecode-tools-0.11.0";
1512 1512 buildInputs = with self; [];
1513 1513 doCheck = false;
1514 propagatedBuildInputs = with self; [click future six Mako MarkupSafe requests Whoosh elasticsearch elasticsearch-dsl urllib3];
1514 propagatedBuildInputs = with self; [click future six Mako MarkupSafe requests elasticsearch elasticsearch-dsl urllib3 Whoosh];
1515 1515 src = fetchurl {
1516 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.10.2.zip";
1517 md5 = "d2af3985a1a32a678944d4d48870cb04";
1516 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.11.0.tar.gz?md5=e5fd0a8363af08a0ced71b50ca9cce15";
1517 md5 = "e5fd0a8363af08a0ced71b50ca9cce15";
1518 1518 };
1519 1519 meta = {
1520 1520 license = [ { fullName = "AGPLv3 and Proprietary"; } ];
1521 1521 };
1522 1522 };
1523 1523 serpent = super.buildPythonPackage {
1524 name = "serpent-1.12";
1524 name = "serpent-1.15";
1525 1525 buildInputs = with self; [];
1526 1526 doCheck = false;
1527 1527 propagatedBuildInputs = with self; [];
1528 1528 src = fetchurl {
1529 url = "https://pypi.python.org/packages/3b/19/1e0e83b47c09edaef8398655088036e7e67386b5c48770218ebb339fbbd5/serpent-1.12.tar.gz";
1530 md5 = "05869ac7b062828b34f8f927f0457b65";
1529 url = "https://pypi.python.org/packages/7b/38/b2b27673a882ff2ea5871bb3e3e6b496ebbaafd1612e51990ffb158b9254/serpent-1.15.tar.gz";
1530 md5 = "e27b1aad5c218e16442f52abb7c7053a";
1531 1531 };
1532 1532 meta = {
1533 1533 license = [ pkgs.lib.licenses.mit ];
1534 1534 };
1535 1535 };
1536 1536 setproctitle = super.buildPythonPackage {
1537 1537 name = "setproctitle-1.1.8";
1538 1538 buildInputs = with self; [];
1539 1539 doCheck = false;
1540 1540 propagatedBuildInputs = with self; [];
1541 1541 src = fetchurl {
1542 1542 url = "https://pypi.python.org/packages/33/c3/ad367a4f4f1ca90468863ae727ac62f6edb558fc09a003d344a02cfc6ea6/setproctitle-1.1.8.tar.gz";
1543 1543 md5 = "728f4c8c6031bbe56083a48594027edd";
1544 1544 };
1545 1545 meta = {
1546 1546 license = [ pkgs.lib.licenses.bsdOriginal ];
1547 1547 };
1548 1548 };
1549 1549 setuptools = super.buildPythonPackage {
1550 name = "setuptools-20.8.1";
1550 name = "setuptools-30.1.0";
1551 1551 buildInputs = with self; [];
1552 1552 doCheck = false;
1553 1553 propagatedBuildInputs = with self; [];
1554 1554 src = fetchurl {
1555 url = "https://pypi.python.org/packages/c4/19/c1bdc88b53da654df43770f941079dbab4e4788c2dcb5658fb86259894c7/setuptools-20.8.1.zip";
1556 md5 = "fe58a5cac0df20bb83942b252a4b0543";
1555 url = "https://pypi.python.org/packages/1e/43/002c8616db9a3e7be23c2556e39b90a32bb40ba0dc652de1999d5334d372/setuptools-30.1.0.tar.gz";
1556 md5 = "cac497f42e5096ac8df29e38d3f81c3e";
1557 1557 };
1558 1558 meta = {
1559 1559 license = [ pkgs.lib.licenses.mit ];
1560 1560 };
1561 1561 };
1562 1562 setuptools-scm = super.buildPythonPackage {
1563 name = "setuptools-scm-1.11.0";
1563 name = "setuptools-scm-1.15.0";
1564 1564 buildInputs = with self; [];
1565 1565 doCheck = false;
1566 1566 propagatedBuildInputs = with self; [];
1567 1567 src = fetchurl {
1568 url = "https://pypi.python.org/packages/cd/5f/e3a038292358058d83d764a47d09114aa5a8003ed4529518f9e580f1a94f/setuptools_scm-1.11.0.tar.gz";
1569 md5 = "4c5c896ba52e134bbc3507bac6400087";
1568 url = "https://pypi.python.org/packages/80/b7/31b6ae5fcb188e37f7e31abe75f9be90490a5456a72860fa6e643f8a3cbc/setuptools_scm-1.15.0.tar.gz";
1569 md5 = "b6916c78ed6253d6602444fad4279c5b";
1570 1570 };
1571 1571 meta = {
1572 1572 license = [ pkgs.lib.licenses.mit ];
1573 1573 };
1574 1574 };
1575 1575 simplegeneric = super.buildPythonPackage {
1576 1576 name = "simplegeneric-0.8.1";
1577 1577 buildInputs = with self; [];
1578 1578 doCheck = false;
1579 1579 propagatedBuildInputs = with self; [];
1580 1580 src = fetchurl {
1581 1581 url = "https://pypi.python.org/packages/3d/57/4d9c9e3ae9a255cd4e1106bb57e24056d3d0709fc01b2e3e345898e49d5b/simplegeneric-0.8.1.zip";
1582 1582 md5 = "f9c1fab00fd981be588fc32759f474e3";
1583 1583 };
1584 1584 meta = {
1585 1585 license = [ pkgs.lib.licenses.zpt21 ];
1586 1586 };
1587 1587 };
1588 1588 simplejson = super.buildPythonPackage {
1589 1589 name = "simplejson-3.7.2";
1590 1590 buildInputs = with self; [];
1591 1591 doCheck = false;
1592 1592 propagatedBuildInputs = with self; [];
1593 1593 src = fetchurl {
1594 1594 url = "https://pypi.python.org/packages/6d/89/7f13f099344eea9d6722779a1f165087cb559598107844b1ac5dbd831fb1/simplejson-3.7.2.tar.gz";
1595 1595 md5 = "a5fc7d05d4cb38492285553def5d4b46";
1596 1596 };
1597 1597 meta = {
1598 1598 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
1599 1599 };
1600 1600 };
1601 1601 six = super.buildPythonPackage {
1602 1602 name = "six-1.9.0";
1603 1603 buildInputs = with self; [];
1604 1604 doCheck = false;
1605 1605 propagatedBuildInputs = with self; [];
1606 1606 src = fetchurl {
1607 1607 url = "https://pypi.python.org/packages/16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz";
1608 1608 md5 = "476881ef4012262dfc8adc645ee786c4";
1609 1609 };
1610 1610 meta = {
1611 1611 license = [ pkgs.lib.licenses.mit ];
1612 1612 };
1613 1613 };
1614 1614 subprocess32 = super.buildPythonPackage {
1615 1615 name = "subprocess32-3.2.6";
1616 1616 buildInputs = with self; [];
1617 1617 doCheck = false;
1618 1618 propagatedBuildInputs = with self; [];
1619 1619 src = fetchurl {
1620 1620 url = "https://pypi.python.org/packages/28/8d/33ccbff51053f59ae6c357310cac0e79246bbed1d345ecc6188b176d72c3/subprocess32-3.2.6.tar.gz";
1621 1621 md5 = "754c5ab9f533e764f931136974b618f1";
1622 1622 };
1623 1623 meta = {
1624 1624 license = [ pkgs.lib.licenses.psfl ];
1625 1625 };
1626 1626 };
1627 1627 supervisor = super.buildPythonPackage {
1628 name = "supervisor-3.3.0";
1628 name = "supervisor-3.3.1";
1629 1629 buildInputs = with self; [];
1630 1630 doCheck = false;
1631 1631 propagatedBuildInputs = with self; [meld3];
1632 1632 src = fetchurl {
1633 url = "https://pypi.python.org/packages/44/80/d28047d120bfcc8158b4e41127706731ee6a3419c661e0a858fb0e7c4b2d/supervisor-3.3.0.tar.gz";
1634 md5 = "46bac00378d1eddb616752b990c67416";
1633 url = "https://pypi.python.org/packages/80/37/964c0d53cbd328796b1aeb7abea4c0f7b0e8c7197ea9b0b9967b7d004def/supervisor-3.3.1.tar.gz";
1634 md5 = "202f760f9bf4930ec06557bac73e5cf2";
1635 1635 };
1636 1636 meta = {
1637 1637 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1638 1638 };
1639 1639 };
1640 termcolor = super.buildPythonPackage {
1641 name = "termcolor-1.1.0";
1642 buildInputs = with self; [];
1643 doCheck = false;
1644 propagatedBuildInputs = with self; [];
1645 src = fetchurl {
1646 url = "https://pypi.python.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz";
1647 md5 = "043e89644f8909d462fbbfa511c768df";
1648 };
1649 meta = {
1650 license = [ pkgs.lib.licenses.mit ];
1651 };
1652 };
1640 1653 traitlets = super.buildPythonPackage {
1641 1654 name = "traitlets-4.3.1";
1642 1655 buildInputs = with self; [];
1643 1656 doCheck = false;
1644 1657 propagatedBuildInputs = with self; [ipython-genutils six decorator enum34];
1645 1658 src = fetchurl {
1646 1659 url = "https://pypi.python.org/packages/b1/d6/5b5aa6d5c474691909b91493da1e8972e309c9f01ecfe4aeafd272eb3234/traitlets-4.3.1.tar.gz";
1647 1660 md5 = "dd0b1b6e5d31ce446d55a4b5e5083c98";
1648 1661 };
1649 1662 meta = {
1650 1663 license = [ pkgs.lib.licenses.bsdOriginal ];
1651 1664 };
1652 1665 };
1653 1666 transifex-client = super.buildPythonPackage {
1654 1667 name = "transifex-client-0.10";
1655 1668 buildInputs = with self; [];
1656 1669 doCheck = false;
1657 1670 propagatedBuildInputs = with self; [];
1658 1671 src = fetchurl {
1659 1672 url = "https://pypi.python.org/packages/f3/4e/7b925192aee656fb3e04fa6381c8b3dc40198047c3b4a356f6cfd642c809/transifex-client-0.10.tar.gz";
1660 1673 md5 = "5549538d84b8eede6b254cd81ae024fa";
1661 1674 };
1662 1675 meta = {
1663 1676 license = [ pkgs.lib.licenses.gpl2 ];
1664 1677 };
1665 1678 };
1666 1679 translationstring = super.buildPythonPackage {
1667 1680 name = "translationstring-1.3";
1668 1681 buildInputs = with self; [];
1669 1682 doCheck = false;
1670 1683 propagatedBuildInputs = with self; [];
1671 1684 src = fetchurl {
1672 1685 url = "https://pypi.python.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz";
1673 1686 md5 = "a4b62e0f3c189c783a1685b3027f7c90";
1674 1687 };
1675 1688 meta = {
1676 1689 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
1677 1690 };
1678 1691 };
1679 1692 trollius = super.buildPythonPackage {
1680 1693 name = "trollius-1.0.4";
1681 1694 buildInputs = with self; [];
1682 1695 doCheck = false;
1683 1696 propagatedBuildInputs = with self; [futures];
1684 1697 src = fetchurl {
1685 1698 url = "https://pypi.python.org/packages/aa/e6/4141db437f55e6ee7a3fb69663239e3fde7841a811b4bef293145ad6c836/trollius-1.0.4.tar.gz";
1686 1699 md5 = "3631a464d49d0cbfd30ab2918ef2b783";
1687 1700 };
1688 1701 meta = {
1689 1702 license = [ pkgs.lib.licenses.asl20 ];
1690 1703 };
1691 1704 };
1692 1705 uWSGI = super.buildPythonPackage {
1693 1706 name = "uWSGI-2.0.11.2";
1694 1707 buildInputs = with self; [];
1695 1708 doCheck = false;
1696 1709 propagatedBuildInputs = with self; [];
1697 1710 src = fetchurl {
1698 1711 url = "https://pypi.python.org/packages/9b/78/918db0cfab0546afa580c1e565209c49aaf1476bbfe491314eadbe47c556/uwsgi-2.0.11.2.tar.gz";
1699 1712 md5 = "1f02dcbee7f6f61de4b1fd68350cf16f";
1700 1713 };
1701 1714 meta = {
1702 1715 license = [ pkgs.lib.licenses.gpl2 ];
1703 1716 };
1704 1717 };
1705 1718 urllib3 = super.buildPythonPackage {
1706 1719 name = "urllib3-1.16";
1707 1720 buildInputs = with self; [];
1708 1721 doCheck = false;
1709 1722 propagatedBuildInputs = with self; [];
1710 1723 src = fetchurl {
1711 1724 url = "https://pypi.python.org/packages/3b/f0/e763169124e3f5db0926bc3dbfcd580a105f9ca44cf5d8e6c7a803c9f6b5/urllib3-1.16.tar.gz";
1712 1725 md5 = "fcaab1c5385c57deeb7053d3d7d81d59";
1713 1726 };
1714 1727 meta = {
1715 1728 license = [ pkgs.lib.licenses.mit ];
1716 1729 };
1717 1730 };
1718 1731 venusian = super.buildPythonPackage {
1719 1732 name = "venusian-1.0";
1720 1733 buildInputs = with self; [];
1721 1734 doCheck = false;
1722 1735 propagatedBuildInputs = with self; [];
1723 1736 src = fetchurl {
1724 1737 url = "https://pypi.python.org/packages/86/20/1948e0dfc4930ddde3da8c33612f6a5717c0b4bc28f591a5c5cf014dd390/venusian-1.0.tar.gz";
1725 1738 md5 = "dccf2eafb7113759d60c86faf5538756";
1726 1739 };
1727 1740 meta = {
1728 1741 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1729 1742 };
1730 1743 };
1731 1744 waitress = super.buildPythonPackage {
1732 name = "waitress-0.8.9";
1745 name = "waitress-1.0.1";
1733 1746 buildInputs = with self; [];
1734 1747 doCheck = false;
1735 propagatedBuildInputs = with self; [setuptools];
1748 propagatedBuildInputs = with self; [];
1736 1749 src = fetchurl {
1737 url = "https://pypi.python.org/packages/ee/65/fc9dee74a909a1187ca51e4f15ad9c4d35476e4ab5813f73421505c48053/waitress-0.8.9.tar.gz";
1738 md5 = "da3f2e62b3676be5dd630703a68e2a04";
1750 url = "https://pypi.python.org/packages/78/7d/84d11b96c3f60164dec3bef4a859a03aeae0231aa93f57fbe0d05fa4ff36/waitress-1.0.1.tar.gz";
1751 md5 = "dda92358a7569669086155923a46e57c";
1739 1752 };
1740 1753 meta = {
1741 1754 license = [ pkgs.lib.licenses.zpt21 ];
1742 1755 };
1743 1756 };
1744 1757 wcwidth = super.buildPythonPackage {
1745 1758 name = "wcwidth-0.1.7";
1746 1759 buildInputs = with self; [];
1747 1760 doCheck = false;
1748 1761 propagatedBuildInputs = with self; [];
1749 1762 src = fetchurl {
1750 1763 url = "https://pypi.python.org/packages/55/11/e4a2bb08bb450fdbd42cc709dd40de4ed2c472cf0ccb9e64af22279c5495/wcwidth-0.1.7.tar.gz";
1751 1764 md5 = "b3b6a0a08f0c8a34d1de8cf44150a4ad";
1752 1765 };
1753 1766 meta = {
1754 1767 license = [ pkgs.lib.licenses.mit ];
1755 1768 };
1756 1769 };
1757 1770 ws4py = super.buildPythonPackage {
1758 1771 name = "ws4py-0.3.5";
1759 1772 buildInputs = with self; [];
1760 1773 doCheck = false;
1761 1774 propagatedBuildInputs = with self; [];
1762 1775 src = fetchurl {
1763 1776 url = "https://pypi.python.org/packages/b6/4f/34af703be86939629479e74d6e650e39f3bd73b3b09212c34e5125764cbc/ws4py-0.3.5.zip";
1764 1777 md5 = "a261b75c20b980e55ce7451a3576a867";
1765 1778 };
1766 1779 meta = {
1767 1780 license = [ pkgs.lib.licenses.bsdOriginal ];
1768 1781 };
1769 1782 };
1770 1783 wsgiref = super.buildPythonPackage {
1771 1784 name = "wsgiref-0.1.2";
1772 1785 buildInputs = with self; [];
1773 1786 doCheck = false;
1774 1787 propagatedBuildInputs = with self; [];
1775 1788 src = fetchurl {
1776 1789 url = "https://pypi.python.org/packages/41/9e/309259ce8dff8c596e8c26df86dbc4e848b9249fd36797fd60be456f03fc/wsgiref-0.1.2.zip";
1777 1790 md5 = "29b146e6ebd0f9fb119fe321f7bcf6cb";
1778 1791 };
1779 1792 meta = {
1780 1793 license = [ { fullName = "PSF or ZPL"; } ];
1781 1794 };
1782 1795 };
1783 1796 zope.cachedescriptors = super.buildPythonPackage {
1784 1797 name = "zope.cachedescriptors-4.0.0";
1785 1798 buildInputs = with self; [];
1786 1799 doCheck = false;
1787 1800 propagatedBuildInputs = with self; [setuptools];
1788 1801 src = fetchurl {
1789 1802 url = "https://pypi.python.org/packages/40/33/694b6644c37f28553f4b9f20b3c3a20fb709a22574dff20b5bdffb09ecd5/zope.cachedescriptors-4.0.0.tar.gz";
1790 1803 md5 = "8d308de8c936792c8e758058fcb7d0f0";
1791 1804 };
1792 1805 meta = {
1793 1806 license = [ pkgs.lib.licenses.zpt21 ];
1794 1807 };
1795 1808 };
1796 1809 zope.deprecation = super.buildPythonPackage {
1797 1810 name = "zope.deprecation-4.1.2";
1798 1811 buildInputs = with self; [];
1799 1812 doCheck = false;
1800 1813 propagatedBuildInputs = with self; [setuptools];
1801 1814 src = fetchurl {
1802 1815 url = "https://pypi.python.org/packages/c1/d3/3919492d5e57d8dd01b36f30b34fc8404a30577392b1eb817c303499ad20/zope.deprecation-4.1.2.tar.gz";
1803 1816 md5 = "e9a663ded58f4f9f7881beb56cae2782";
1804 1817 };
1805 1818 meta = {
1806 1819 license = [ pkgs.lib.licenses.zpt21 ];
1807 1820 };
1808 1821 };
1809 1822 zope.event = super.buildPythonPackage {
1810 1823 name = "zope.event-4.0.3";
1811 1824 buildInputs = with self; [];
1812 1825 doCheck = false;
1813 1826 propagatedBuildInputs = with self; [setuptools];
1814 1827 src = fetchurl {
1815 1828 url = "https://pypi.python.org/packages/c1/29/91ba884d7d6d96691df592e9e9c2bfa57a47040ec1ff47eff18c85137152/zope.event-4.0.3.tar.gz";
1816 1829 md5 = "9a3780916332b18b8b85f522bcc3e249";
1817 1830 };
1818 1831 meta = {
1819 1832 license = [ pkgs.lib.licenses.zpt21 ];
1820 1833 };
1821 1834 };
1822 1835 zope.interface = super.buildPythonPackage {
1823 1836 name = "zope.interface-4.1.3";
1824 1837 buildInputs = with self; [];
1825 1838 doCheck = false;
1826 1839 propagatedBuildInputs = with self; [setuptools];
1827 1840 src = fetchurl {
1828 1841 url = "https://pypi.python.org/packages/9d/81/2509ca3c6f59080123c1a8a97125eb48414022618cec0e64eb1313727bfe/zope.interface-4.1.3.tar.gz";
1829 1842 md5 = "9ae3d24c0c7415deb249dd1a132f0f79";
1830 1843 };
1831 1844 meta = {
1832 1845 license = [ pkgs.lib.licenses.zpt21 ];
1833 1846 };
1834 1847 };
1835 1848
1836 1849 ### Test requirements
1837 1850
1838 pytest-sugar = super.buildPythonPackage {
1839 name = "pytest-sugar-0.7.1";
1840 buildInputs = with self; [];
1841 doCheck = false;
1842 propagatedBuildInputs = with self; [pytest termcolor];
1843 src = fetchurl {
1844 url = "https://pypi.python.org/packages/03/97/05d988b4fa870e7373e8ee4582408543b9ca2bd35c3c67b569369c6f9c49/pytest-sugar-0.7.1.tar.gz";
1845 md5 = "7400f7c11f3d572b2c2a3b60352d35fe";
1846 };
1847 meta = {
1848 license = [ pkgs.lib.licenses.bsdOriginal ];
1849 };
1850 };
1851 termcolor = super.buildPythonPackage {
1852 name = "termcolor-1.1.0";
1853 buildInputs = with self; [];
1854 doCheck = false;
1855 propagatedBuildInputs = with self; [];
1856 src = fetchurl {
1857 url = "https://pypi.python.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz";
1858 md5 = "043e89644f8909d462fbbfa511c768df";
1859 };
1860 meta = {
1861 license = [ pkgs.lib.licenses.mit ];
1862 };
1863 };
1851
1864 1852 }
@@ -1,150 +1,131 b''
1 Babel==1.3
2 Beaker==1.7.0
3 Chameleon==2.24
4 CProfileV==1.0.6
5 FormEncode==1.2.4
6 Jinja2==2.7.3
7 Mako==1.0.1
8 Markdown==2.6.2
9 MarkupSafe==0.23
10 MySQL-python==1.2.5
11 Paste==2.0.2
12 PasteDeploy==1.5.2
13 PasteScript==1.7.5
14 Pygments==2.1.3
15 pygments-markdown-lexer==0.1.0.dev39
16
17 # TODO: This version is not available on PyPI
18 # Pylons==1.0.2.dev20160108
19 Pylons==1.0.1
1 ## core
2 setuptools==30.1.0
3 setuptools-scm==1.15.0
20 4
21 # TODO: This version is not available, but newer ones are
22 # Pyro4==4.35
23 Pyro4==4.41
24
25 # TODO: This should probably not be in here
26 # -e hg+https://johbo@code.rhodecode.com/johbo/rhodecode-fork@3a454bd1f17c0b2b2a951cf2b111e0320d7942a9#egg=RhodeCodeEnterprise-dev
27
28 Routes==1.13
29 SQLAlchemy==0.9.9
30 Sphinx==1.2.2
31 Tempita==0.5.2
32 URLObject==2.4.0
33 WebError==0.10.3
34
35 # TODO: This is modified by us, needs a better integration. For now
36 # using the latest version before.
37 # WebHelpers==1.3.dev20150807
38 WebHelpers==1.3
39
40 WebHelpers2==2.0
41 WebOb==1.3.1
42 WebTest==1.4.3
43 Whoosh==2.7.0
44 alembic==0.8.4
45 5 amqplib==1.0.2
46 6 anyjson==0.3.3
47 appenlight-client==0.6.14
48 authomatic==0.1.0.post1;
7 authomatic==0.1.0.post1
8 Babel==1.3
49 9 backport-ipaddress==0.1
50 bottle==0.12.8
51 bumpversion==0.5.3
10 Beaker==1.7.0
52 11 celery==2.2.10
12 Chameleon==2.24
53 13 channelstream==0.5.2
54 14 click==5.1
55 15 colander==1.2
56 16 configobj==5.0.6
57 cov-core==1.15.0
58 coverage==3.7.1
59 cssselect==0.9.1
60 17 decorator==3.4.2
61 18 deform==2.0a2
62 19 docutils==0.12
63 20 dogpile.cache==0.6.1
64 21 dogpile.core==0.4.1
65 dulwich==0.12.0
66 22 ecdsa==0.11
23 FormEncode==1.2.4
67 24 future==0.14.3
68 25 futures==3.0.2
69 gevent==1.1.1
70 gprof2dot==2015.12.1
71 greenlet==0.4.9
72 gunicorn==19.6.0
73
74 # TODO: Needs subvertpy and blows up without Subversion headers,
75 # actually we should not need this for Enterprise at all.
76 # hgsubversion==1.8.2
77
78 26 gnureadline==6.3.3
79 27 infrae.cache==1.0.1
80 invoke==0.13.0
81 ipdb==0.10.1
82 ipython==5.1.0
83 28 iso8601==0.1.11
84 29 itsdangerous==0.24
30 Jinja2==2.7.3
85 31 kombu==1.5.1
86 lxml==3.4.4
32 Mako==1.0.6
33 Markdown==2.6.7
34 MarkupSafe==0.23
87 35 meld3==1.0.2
88 mock==1.0.1
89 msgpack-python==0.4.6
36 msgpack-python==0.4.8
37 MySQL-python==1.2.5
90 38 nose==1.3.6
91 39 objgraph==2.0.0
92 40 packaging==15.2
93 41 paramiko==1.15.1
42 Paste==2.0.3
43 PasteDeploy==1.5.2
44 PasteScript==1.7.5
94 45 psutil==4.3.1
95 46 psycopg2==2.6.1
96 py==1.4.29
97 47 py-bcrypt==0.4
98 py-gfm==0.1.3
99 48 pycrypto==2.6.1
100 49 pycurl==7.19.5
101 50 pyflakes==0.8.1
51 pygments-markdown-lexer==0.1.0.dev39
52 Pygments==2.2.0
102 53 pyparsing==1.5.7
103 pyramid==1.6.1
104 54 pyramid-beaker==0.8
105 55 pyramid-debugtoolbar==2.4.2
106 56 pyramid-jinja2==2.5
107 57 pyramid-mako==1.0.2
58 pyramid==1.6.1
108 59 pysqlite==2.6.3
109 pytest==2.8.5
110 pytest-runner==2.7.1
111 pytest-catchlog==1.2.2
112 pytest-cov==1.8.1
113 pytest-profiling==1.0.1
114 pytest-timeout==0.4
115 60 python-dateutil==1.5
116 61 python-ldap==2.4.19
117 62 python-memcached==1.57
118 63 python-pam==1.8.2
119 64 pytz==2015.4
120 65 pyzmq==14.6.0
121
122 # TODO: This is not available in public
123 # rc-testdata==0.2.0
124
125 https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.10.2.zip#md5=d2af3985a1a32a678944d4d48870cb04
126
127
128 66 recaptcha-client==1.0.6
129 67 repoze.lru==0.6
130 68 requests==2.9.1
131 serpent==1.12
69 Routes==1.13
132 70 setproctitle==1.1.8
133 setuptools==20.8.1
134 setuptools-scm==1.11.0
135 71 simplejson==3.7.2
136 72 six==1.9.0
73 Sphinx==1.2.2
74 SQLAlchemy==0.9.9
137 75 subprocess32==3.2.6
138 supervisor==3.3.0
139 transifex-client==0.10
76 supervisor==3.3.1
77 Tempita==0.5.2
140 78 translationstring==1.3
141 79 trollius==1.0.4
142 uWSGI==2.0.11.2
143 80 urllib3==1.16
81 URLObject==2.4.0
144 82 venusian==1.0
145 waitress==0.8.9
83 WebError==0.10.3
84 WebHelpers2==2.0
85 WebHelpers==1.3
86 WebOb==1.3.1
87 Whoosh==2.7.4
146 88 wsgiref==0.1.2
147 89 zope.cachedescriptors==4.0.0
148 90 zope.deprecation==4.1.2
149 91 zope.event==4.0.3
150 92 zope.interface==4.1.3
93
94 ## customized/patched libs
95 # our patched version of Pylons==1.0.2
96 https://code.rhodecode.com/upstream/pylons/archive/707354ee4261b9c10450404fc9852ccea4fd667d.tar.gz?md5=f26633726fa2cd3a340316ee6a5d218f#egg=Pylons==1.0.2.rhodecode-patch-1
97 # not released py-gfm==0.1.3
98 https://code.rhodecode.com/upstream/py-gfm/archive/0d66a19bc16e3d49de273c0f797d4e4781e8c0f2.tar.gz?md5=0d0d5385bfb629eea636a80b9c2bfd16#egg=py-gfm==0.1.3.rhodecode-upstream1
99
100
101 ## cli tools
102 alembic==0.8.4
103 invoke==0.13.0
104 bumpversion==0.5.3
105 transifex-client==0.10
106
107 ## http servers
108 gevent==1.1.2
109 greenlet==0.4.10
110 gunicorn==19.6.0
111 waitress==1.0.1
112 uWSGI==2.0.11.2
113
114 ## debug
115 ipdb==0.10.1
116 ipython==5.1.0
117 CProfileV==1.0.6
118 bottle==0.12.8
119
120 ## rhodecode-tools, special case
121 https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.11.0.tar.gz?md5=e5fd0a8363af08a0ced71b50ca9cce15#egg=rhodecode-tools==0.11.0
122
123 ## appenlight
124 appenlight-client==0.6.14
125
126 # Pyro/Deprecated TODO(Marcink): remove in 4.7 release.
127 Pyro4==4.41
128 serpent==1.15
129
130 ## test related requirements
131 -r requirements_test.txt
@@ -1,1 +1,1 b''
1 4.5.2 No newline at end of file
1 4.6.0 No newline at end of file
@@ -1,63 +1,63 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 """
22 22
23 23 RhodeCode, a web based repository management software
24 24 versioning implementation: http://www.python.org/dev/peps/pep-0386/
25 25 """
26 26
27 27 import os
28 28 import sys
29 29 import platform
30 30
31 31 VERSION = tuple(open(os.path.join(
32 32 os.path.dirname(__file__), 'VERSION')).read().split('.'))
33 33
34 34 BACKENDS = {
35 35 'hg': 'Mercurial repository',
36 36 'git': 'Git repository',
37 37 'svn': 'Subversion repository',
38 38 }
39 39
40 40 CELERY_ENABLED = False
41 41 CELERY_EAGER = False
42 42
43 43 # link to config for pylons
44 44 CONFIG = {}
45 45
46 46 # Populated with the settings dictionary from application init in
47 47 # rhodecode.conf.environment.load_pyramid_environment
48 48 PYRAMID_SETTINGS = {}
49 49
50 50 # Linked module for extensions
51 51 EXTENSIONS = {}
52 52
53 53 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
54 __dbversion__ = 63 # defines current db version for migrations
54 __dbversion__ = 64 # defines current db version for migrations
55 55 __platform__ = platform.system()
56 56 __license__ = 'AGPLv3, and Commercial License'
57 57 __author__ = 'RhodeCode GmbH'
58 __url__ = 'http://rhodecode.com'
58 __url__ = 'https://code.rhodecode.com'
59 59
60 60 is_windows = __platform__ in ['Windows']
61 61 is_unix = not is_windows
62 62 is_test = False
63 63 disable_error_handler = False
@@ -1,43 +1,57 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 from rhodecode.admin.navigation import NavigationRegistry
23 23 from rhodecode.config.routing import ADMIN_PREFIX
24 24 from rhodecode.lib.utils2 import str2bool
25 25
26 26
27 27 def includeme(config):
28 28 settings = config.get_settings()
29 29
30 30 # Create admin navigation registry and add it to the pyramid registry.
31 31 labs_active = str2bool(settings.get('labs_settings_active', False))
32 32 navigation_registry = NavigationRegistry(labs_active=labs_active)
33 33 config.registry.registerUtility(navigation_registry)
34 34
35 35 config.add_route(
36 36 name='admin_settings_open_source',
37 37 pattern=ADMIN_PREFIX + '/settings/open_source')
38 38 config.add_route(
39 39 name='admin_settings_vcs_svn_generate_cfg',
40 40 pattern=ADMIN_PREFIX + '/settings/vcs/svn_generate_cfg')
41 41
42 config.add_route(
43 name='admin_settings_system',
44 pattern=ADMIN_PREFIX + '/settings/system')
45 config.add_route(
46 name='admin_settings_system_update',
47 pattern=ADMIN_PREFIX + '/settings/system/updates')
48
49 config.add_route(
50 name='admin_settings_sessions',
51 pattern=ADMIN_PREFIX + '/settings/sessions')
52 config.add_route(
53 name='admin_settings_sessions_cleanup',
54 pattern=ADMIN_PREFIX + '/settings/sessions/cleanup')
55
42 56 # Scan module for configuration decorators.
43 57 config.scan()
@@ -1,29 +1,29 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 from zope.interface import Interface
22 22
23 23
24 24 class IAdminNavigationRegistry(Interface):
25 25 """
26 26 Interface for the admin navigation registry. Currently this is only
27 27 used to register and retrieve it via pyramids registry.
28 28 """
29 29 pass
@@ -1,126 +1,140 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import logging
23 23 import collections
24 24
25 25 from pylons import url
26 26 from zope.interface import implementer
27 27
28 28 from rhodecode.admin.interfaces import IAdminNavigationRegistry
29 29 from rhodecode.lib.utils import get_registry
30 30 from rhodecode.translation import _
31 31
32 32
33 33 log = logging.getLogger(__name__)
34 34
35 35 NavListEntry = collections.namedtuple('NavListEntry', ['key', 'name', 'url'])
36 36
37 37
38 38 class NavEntry(object):
39 39 """
40 40 Represents an entry in the admin navigation.
41 41
42 42 :param key: Unique identifier used to store reference in an OrderedDict.
43 43 :param name: Display name, usually a translation string.
44 44 :param view_name: Name of the view, used generate the URL.
45 45 :param pyramid: Indicator to use pyramid for URL generation. This should
46 46 be removed as soon as we are fully migrated to pyramid.
47 47 """
48 48
49 49 def __init__(self, key, name, view_name, pyramid=False):
50 50 self.key = key
51 51 self.name = name
52 52 self.view_name = view_name
53 53 self.pyramid = pyramid
54 54
55 55 def generate_url(self, request):
56 56 if self.pyramid:
57 57 if hasattr(request, 'route_path'):
58 58 return request.route_path(self.view_name)
59 59 else:
60 60 # TODO: johbo: Remove this after migrating to pyramid.
61 61 # We need the pyramid request here to generate URLs to pyramid
62 62 # views from within pylons views.
63 63 from pyramid.threadlocal import get_current_request
64 64 pyramid_request = get_current_request()
65 65 return pyramid_request.route_path(self.view_name)
66 66 else:
67 67 return url(self.view_name)
68 68
69 def get_localized_name(self, request):
70 if hasattr(request, 'translate'):
71 return request.translate(self.name)
72 else:
73 # TODO(marcink): Remove this after migrating to pyramid
74 from pyramid.threadlocal import get_current_request
75 pyramid_request = get_current_request()
76 return pyramid_request.translate(self.name)
77
69 78
70 79 @implementer(IAdminNavigationRegistry)
71 80 class NavigationRegistry(object):
72 81
73 82 _base_entries = [
74 83 NavEntry('global', _('Global'), 'admin_settings_global'),
75 84 NavEntry('vcs', _('VCS'), 'admin_settings_vcs'),
76 85 NavEntry('visual', _('Visual'), 'admin_settings_visual'),
77 86 NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'),
78 87 NavEntry('issuetracker', _('Issue Tracker'),
79 88 'admin_settings_issuetracker'),
80 89 NavEntry('email', _('Email'), 'admin_settings_email'),
81 90 NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
82 91 NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
92
83 93 NavEntry('integrations', _('Integrations'),
84 94 'global_integrations_home', pyramid=True),
85 NavEntry('system', _('System Info'), 'admin_settings_system'),
95 NavEntry('system', _('System Info'),
96 'admin_settings_system', pyramid=True),
97 NavEntry('sessions', _('User Sessions'),
98 'admin_settings_sessions', pyramid=True),
86 99 NavEntry('open_source', _('Open Source Licenses'),
87 100 'admin_settings_open_source', pyramid=True),
101
88 102 # TODO: marcink: we disable supervisor now until the supervisor stats
89 103 # page is fixed in the nix configuration
90 104 # NavEntry('supervisor', _('Supervisor'), 'admin_settings_supervisor'),
91 105 ]
92 106
93 _labs_entry = NavEntry('labs', _('Labs'),
94 'admin_settings_labs')
107 _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs')
95 108
96 109 def __init__(self, labs_active=False):
97 110 self._registered_entries = collections.OrderedDict([
98 111 (item.key, item) for item in self.__class__._base_entries
99 112 ])
100 113
101 114 if labs_active:
102 115 self.add_entry(self._labs_entry)
103 116
104 117 def add_entry(self, entry):
105 118 self._registered_entries[entry.key] = entry
106 119
107 120 def get_navlist(self, request):
108 navlist = [NavListEntry(i.key, i.name, i.generate_url(request))
121 navlist = [NavListEntry(i.key, i.get_localized_name(request),
122 i.generate_url(request))
109 123 for i in self._registered_entries.values()]
110 124 return navlist
111 125
112 126
113 127 def navigation_registry(request):
114 128 """
115 129 Helper that returns the admin navigation registry.
116 130 """
117 131 pyramid_registry = get_registry(request)
118 132 nav_registry = pyramid_registry.queryUtility(IAdminNavigationRegistry)
119 133 return nav_registry
120 134
121 135
122 136 def navigation_list(request):
123 137 """
124 138 Helper that returns the admin navigation as list of NavListEntry objects.
125 139 """
126 140 return navigation_registry(request).get_navlist(request)
@@ -1,505 +1,507 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2016 RhodeCode GmbH
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import inspect
22 22 import itertools
23 23 import logging
24 24 import types
25 25
26 26 import decorator
27 27 import venusian
28 28 from collections import OrderedDict
29 29
30 30 from pyramid.exceptions import ConfigurationError
31 31 from pyramid.renderers import render
32 32 from pyramid.response import Response
33 33 from pyramid.httpexceptions import HTTPNotFound
34 34
35 35 from rhodecode.api.exc import (
36 36 JSONRPCBaseError, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
37 37 from rhodecode.lib.auth import AuthUser
38 38 from rhodecode.lib.base import get_ip_addr
39 39 from rhodecode.lib.ext_json import json
40 40 from rhodecode.lib.utils2 import safe_str
41 41 from rhodecode.lib.plugins.utils import get_plugin_settings
42 42 from rhodecode.model.db import User, UserApiKeys
43 43
44 44 log = logging.getLogger(__name__)
45 45
46 46 DEFAULT_RENDERER = 'jsonrpc_renderer'
47 47 DEFAULT_URL = '/_admin/apiv2'
48 48
49 49
50 50 class ExtJsonRenderer(object):
51 51 """
52 52 Custom renderer that mkaes use of our ext_json lib
53 53
54 54 """
55 55
56 56 def __init__(self, serializer=json.dumps, **kw):
57 57 """ Any keyword arguments will be passed to the ``serializer``
58 58 function."""
59 59 self.serializer = serializer
60 60 self.kw = kw
61 61
62 62 def __call__(self, info):
63 63 """ Returns a plain JSON-encoded string with content-type
64 64 ``application/json``. The content-type may be overridden by
65 65 setting ``request.response.content_type``."""
66 66
67 67 def _render(value, system):
68 68 request = system.get('request')
69 69 if request is not None:
70 70 response = request.response
71 71 ct = response.content_type
72 72 if ct == response.default_content_type:
73 73 response.content_type = 'application/json'
74 74
75 75 return self.serializer(value, **self.kw)
76 76
77 77 return _render
78 78
79 79
80 80 def jsonrpc_response(request, result):
81 81 rpc_id = getattr(request, 'rpc_id', None)
82 82 response = request.response
83 83
84 84 # store content_type before render is called
85 85 ct = response.content_type
86 86
87 87 ret_value = ''
88 88 if rpc_id:
89 89 ret_value = {
90 90 'id': rpc_id,
91 91 'result': result,
92 92 'error': None,
93 93 }
94 94
95 95 # fetch deprecation warnings, and store it inside results
96 96 deprecation = getattr(request, 'rpc_deprecation', None)
97 97 if deprecation:
98 98 ret_value['DEPRECATION_WARNING'] = deprecation
99 99
100 100 raw_body = render(DEFAULT_RENDERER, ret_value, request=request)
101 101 response.body = safe_str(raw_body, response.charset)
102 102
103 103 if ct == response.default_content_type:
104 104 response.content_type = 'application/json'
105 105
106 106 return response
107 107
108 108
109 109 def jsonrpc_error(request, message, retid=None, code=None):
110 110 """
111 111 Generate a Response object with a JSON-RPC error body
112 112
113 113 :param code:
114 114 :param retid:
115 115 :param message:
116 116 """
117 117 err_dict = {'id': retid, 'result': None, 'error': message}
118 118 body = render(DEFAULT_RENDERER, err_dict, request=request).encode('utf-8')
119 119 return Response(
120 120 body=body,
121 121 status=code,
122 122 content_type='application/json'
123 123 )
124 124
125 125
126 126 def exception_view(exc, request):
127 127 rpc_id = getattr(request, 'rpc_id', None)
128 128
129 129 fault_message = 'undefined error'
130 130 if isinstance(exc, JSONRPCError):
131 131 fault_message = exc.message
132 132 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
133 133 elif isinstance(exc, JSONRPCValidationError):
134 134 colander_exc = exc.colander_exception
135 #TODO: think maybe of nicer way to serialize errors ?
135 # TODO(marcink): think maybe of nicer way to serialize errors ?
136 136 fault_message = colander_exc.asdict()
137 137 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
138 138 elif isinstance(exc, JSONRPCForbidden):
139 139 fault_message = 'Access was denied to this resource.'
140 140 log.warning('json-rpc forbidden call rpc_id:%s "%s"', rpc_id, fault_message)
141 141 elif isinstance(exc, HTTPNotFound):
142 142 method = request.rpc_method
143 143 log.debug('json-rpc method `%s` not found in list of '
144 144 'api calls: %s, rpc_id:%s',
145 145 method, request.registry.jsonrpc_methods.keys(), rpc_id)
146 146 fault_message = "No such method: {}".format(method)
147 147
148 148 return jsonrpc_error(request, fault_message, rpc_id)
149 149
150 150
151 151 def request_view(request):
152 152 """
153 153 Main request handling method. It handles all logic to call a specific
154 154 exposed method
155 155 """
156 156
157 157 # check if we can find this session using api_key, get_by_auth_token
158 158 # search not expired tokens only
159 159
160 160 try:
161 161 u = User.get_by_auth_token(request.rpc_api_key)
162 162
163 163 if u is None:
164 164 return jsonrpc_error(
165 165 request, retid=request.rpc_id, message='Invalid API KEY')
166 166
167 167 if not u.active:
168 168 return jsonrpc_error(
169 169 request, retid=request.rpc_id,
170 170 message='Request from this user not allowed')
171 171
172 172 # check if we are allowed to use this IP
173 173 auth_u = AuthUser(
174 174 u.user_id, request.rpc_api_key, ip_addr=request.rpc_ip_addr)
175 175 if not auth_u.ip_allowed:
176 176 return jsonrpc_error(
177 177 request, retid=request.rpc_id,
178 178 message='Request from IP:%s not allowed' % (
179 179 request.rpc_ip_addr,))
180 180 else:
181 181 log.info('Access for IP:%s allowed' % (request.rpc_ip_addr,))
182 182
183 183 # now check if token is valid for API
184 184 role = UserApiKeys.ROLE_API
185 185 extra_auth_tokens = [
186 186 x.api_key for x in User.extra_valid_auth_tokens(u, role=role)]
187 187 active_tokens = [u.api_key] + extra_auth_tokens
188 188
189 189 log.debug('Checking if API key has proper role')
190 190 if request.rpc_api_key not in active_tokens:
191 191 return jsonrpc_error(
192 192 request, retid=request.rpc_id,
193 193 message='API KEY has bad role for an API call')
194 194
195 195 except Exception as e:
196 196 log.exception('Error on API AUTH')
197 197 return jsonrpc_error(
198 198 request, retid=request.rpc_id, message='Invalid API KEY')
199 199
200 200 method = request.rpc_method
201 201 func = request.registry.jsonrpc_methods[method]
202 202
203 203 # now that we have a method, add request._req_params to
204 204 # self.kargs and dispatch control to WGIController
205 205 argspec = inspect.getargspec(func)
206 206 arglist = argspec[0]
207 207 defaults = map(type, argspec[3] or [])
208 208 default_empty = types.NotImplementedType
209 209
210 210 # kw arguments required by this method
211 211 func_kwargs = dict(itertools.izip_longest(
212 212 reversed(arglist), reversed(defaults), fillvalue=default_empty))
213 213
214 214 # This attribute will need to be first param of a method that uses
215 215 # api_key, which is translated to instance of user at that name
216 216 user_var = 'apiuser'
217 217 request_var = 'request'
218 218
219 219 for arg in [user_var, request_var]:
220 220 if arg not in arglist:
221 221 return jsonrpc_error(
222 222 request,
223 223 retid=request.rpc_id,
224 224 message='This method [%s] does not support '
225 225 'required parameter `%s`' % (func.__name__, arg))
226 226
227 227 # get our arglist and check if we provided them as args
228 228 for arg, default in func_kwargs.items():
229 229 if arg in [user_var, request_var]:
230 230 # user_var and request_var are pre-hardcoded parameters and we
231 231 # don't need to do any translation
232 232 continue
233 233
234 234 # skip the required param check if it's default value is
235 235 # NotImplementedType (default_empty)
236 236 if default == default_empty and arg not in request.rpc_params:
237 237 return jsonrpc_error(
238 238 request,
239 239 retid=request.rpc_id,
240 240 message=('Missing non optional `%s` arg in JSON DATA' % arg)
241 241 )
242 242
243 # sanitze extra passed arguments
243 # sanitize extra passed arguments
244 244 for k in request.rpc_params.keys()[:]:
245 245 if k not in func_kwargs:
246 246 del request.rpc_params[k]
247 247
248 248 call_params = request.rpc_params
249 249 call_params.update({
250 250 'request': request,
251 251 'apiuser': auth_u
252 252 })
253 253 try:
254 254 ret_value = func(**call_params)
255 255 return jsonrpc_response(request, ret_value)
256 256 except JSONRPCBaseError:
257 257 raise
258 258 except Exception:
259 log.exception('Unhandled exception occured on api call: %s', func)
259 log.exception('Unhandled exception occurred on api call: %s', func)
260 260 return jsonrpc_error(request, retid=request.rpc_id,
261 261 message='Internal server error')
262 262
263 263
264 264 def setup_request(request):
265 265 """
266 266 Parse a JSON-RPC request body. It's used inside the predicates method
267 267 to validate and bootstrap requests for usage in rpc calls.
268 268
269 269 We need to raise JSONRPCError here if we want to return some errors back to
270 270 user.
271 271 """
272
272 273 log.debug('Executing setup request: %r', request)
273 274 request.rpc_ip_addr = get_ip_addr(request.environ)
274 # TODO: marcink, deprecate GET at some point
275 # TODO(marcink): deprecate GET at some point
275 276 if request.method not in ['POST', 'GET']:
276 277 log.debug('unsupported request method "%s"', request.method)
277 278 raise JSONRPCError(
278 279 'unsupported request method "%s". Please use POST' % request.method)
279 280
280 281 if 'CONTENT_LENGTH' not in request.environ:
281 282 log.debug("No Content-Length")
282 283 raise JSONRPCError("Empty body, No Content-Length in request")
283 284
284 285 else:
285 286 length = request.environ['CONTENT_LENGTH']
286 287 log.debug('Content-Length: %s', length)
287 288
288 289 if length == 0:
289 290 log.debug("Content-Length is 0")
290 291 raise JSONRPCError("Content-Length is 0")
291 292
292 293 raw_body = request.body
293 294 try:
294 295 json_body = json.loads(raw_body)
295 296 except ValueError as e:
296 297 # catch JSON errors Here
297 298 raise JSONRPCError("JSON parse error ERR:%s RAW:%r" % (e, raw_body))
298 299
299 300 request.rpc_id = json_body.get('id')
300 301 request.rpc_method = json_body.get('method')
301 302
302 303 # check required base parameters
303 304 try:
304 305 api_key = json_body.get('api_key')
305 306 if not api_key:
306 307 api_key = json_body.get('auth_token')
307 308
308 309 if not api_key:
309 310 raise KeyError('api_key or auth_token')
310 311
312 # TODO(marcink): support passing in token in request header
313
311 314 request.rpc_api_key = api_key
312 315 request.rpc_id = json_body['id']
313 316 request.rpc_method = json_body['method']
314 317 request.rpc_params = json_body['args'] \
315 318 if isinstance(json_body['args'], dict) else {}
316 319
317 320 log.debug(
318 321 'method: %s, params: %s' % (request.rpc_method, request.rpc_params))
319 322 except KeyError as e:
320 323 raise JSONRPCError('Incorrect JSON data. Missing %s' % e)
321 324
322 325 log.debug('setup complete, now handling method:%s rpcid:%s',
323 326 request.rpc_method, request.rpc_id, )
324 327
325 328
326 329 class RoutePredicate(object):
327 330 def __init__(self, val, config):
328 331 self.val = val
329 332
330 333 def text(self):
331 334 return 'jsonrpc route = %s' % self.val
332 335
333 336 phash = text
334 337
335 338 def __call__(self, info, request):
336 339 if self.val:
337 340 # potentially setup and bootstrap our call
338 341 setup_request(request)
339 342
340 343 # Always return True so that even if it isn't a valid RPC it
341 344 # will fall through to the underlaying handlers like notfound_view
342 345 return True
343 346
344 347
345 348 class NotFoundPredicate(object):
346 349 def __init__(self, val, config):
347 350 self.val = val
348 351
349 352 def text(self):
350 353 return 'jsonrpc method not found = %s' % self.val
351 354
352 355 phash = text
353 356
354 357 def __call__(self, info, request):
355 358 return hasattr(request, 'rpc_method')
356 359
357 360
358 361 class MethodPredicate(object):
359 362 def __init__(self, val, config):
360 363 self.method = val
361 364
362 365 def text(self):
363 366 return 'jsonrpc method = %s' % self.method
364 367
365 368 phash = text
366 369
367 370 def __call__(self, context, request):
368 371 # we need to explicitly return False here, so pyramid doesn't try to
369 372 # execute our view directly. We need our main handler to execute things
370 373 return getattr(request, 'rpc_method') == self.method
371 374
372 375
373 376 def add_jsonrpc_method(config, view, **kwargs):
374 377 # pop the method name
375 378 method = kwargs.pop('method', None)
376 379
377 380 if method is None:
378 381 raise ConfigurationError(
379 382 'Cannot register a JSON-RPC method without specifying the '
380 383 '"method"')
381 384
382 385 # we define custom predicate, to enable to detect conflicting methods,
383 386 # those predicates are kind of "translation" from the decorator variables
384 387 # to internal predicates names
385 388
386 389 kwargs['jsonrpc_method'] = method
387 390
388 391 # register our view into global view store for validation
389 392 config.registry.jsonrpc_methods[method] = view
390 393
391 394 # we're using our main request_view handler, here, so each method
392 395 # has a unified handler for itself
393 396 config.add_view(request_view, route_name='apiv2', **kwargs)
394 397
395 398
396 399 class jsonrpc_method(object):
397 400 """
398 401 decorator that works similar to @add_view_config decorator,
399 402 but tailored for our JSON RPC
400 403 """
401 404
402 405 venusian = venusian # for testing injection
403 406
404 407 def __init__(self, method=None, **kwargs):
405 408 self.method = method
406 409 self.kwargs = kwargs
407 410
408 411 def __call__(self, wrapped):
409 412 kwargs = self.kwargs.copy()
410 413 kwargs['method'] = self.method or wrapped.__name__
411 414 depth = kwargs.pop('_depth', 0)
412 415
413 416 def callback(context, name, ob):
414 417 config = context.config.with_package(info.module)
415 418 config.add_jsonrpc_method(view=ob, **kwargs)
416 419
417 420 info = venusian.attach(wrapped, callback, category='pyramid',
418 421 depth=depth + 1)
419 422 if info.scope == 'class':
420 423 # ensure that attr is set if decorating a class method
421 424 kwargs.setdefault('attr', wrapped.__name__)
422 425
423 426 kwargs['_info'] = info.codeinfo # fbo action_method
424 427 return wrapped
425 428
426 429
427 430 class jsonrpc_deprecated_method(object):
428 431 """
429 432 Marks method as deprecated, adds log.warning, and inject special key to
430 433 the request variable to mark method as deprecated.
431 434 Also injects special docstring that extract_docs will catch to mark
432 435 method as deprecated.
433 436
434 437 :param use_method: specify which method should be used instead of
435 438 the decorated one
436 439
437 440 Use like::
438 441
439 442 @jsonrpc_method()
440 443 @jsonrpc_deprecated_method(use_method='new_func', deprecated_at_version='3.0.0')
441 444 def old_func(request, apiuser, arg1, arg2):
442 445 ...
443 446 """
444 447
445 448 def __init__(self, use_method, deprecated_at_version):
446 449 self.use_method = use_method
447 450 self.deprecated_at_version = deprecated_at_version
448 451 self.deprecated_msg = ''
449 452
450 453 def __call__(self, func):
451 454 self.deprecated_msg = 'Please use method `{method}` instead.'.format(
452 455 method=self.use_method)
453 456
454 457 docstring = """\n
455 458 .. deprecated:: {version}
456 459
457 460 {deprecation_message}
458 461
459 462 {original_docstring}
460 463 """
461 464 func.__doc__ = docstring.format(
462 465 version=self.deprecated_at_version,
463 466 deprecation_message=self.deprecated_msg,
464 467 original_docstring=func.__doc__)
465 468 return decorator.decorator(self.__wrapper, func)
466 469
467 470 def __wrapper(self, func, *fargs, **fkwargs):
468 471 log.warning('DEPRECATED API CALL on function %s, please '
469 472 'use `%s` instead', func, self.use_method)
470 473 # alter function docstring to mark as deprecated, this is picked up
471 474 # via fabric file that generates API DOC.
472 475 result = func(*fargs, **fkwargs)
473 476
474 477 request = fargs[0]
475 478 request.rpc_deprecation = 'DEPRECATED METHOD ' + self.deprecated_msg
476 479 return result
477 480
478 481
479 482 def includeme(config):
480 483 plugin_module = 'rhodecode.api'
481 484 plugin_settings = get_plugin_settings(
482 485 plugin_module, config.registry.settings)
483 486
484 487 if not hasattr(config.registry, 'jsonrpc_methods'):
485 488 config.registry.jsonrpc_methods = OrderedDict()
486 489
487 490 # match filter by given method only
488 config.add_view_predicate(
489 'jsonrpc_method', MethodPredicate)
491 config.add_view_predicate('jsonrpc_method', MethodPredicate)
490 492
491 493 config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer(
492 494 serializer=json.dumps, indent=4))
493 495 config.add_directive('add_jsonrpc_method', add_jsonrpc_method)
494 496
495 497 config.add_route_predicate(
496 498 'jsonrpc_call', RoutePredicate)
497 499
498 500 config.add_route(
499 501 'apiv2', plugin_settings.get('url', DEFAULT_URL), jsonrpc_call=True)
500 502
501 503 config.scan(plugin_module, ignore='rhodecode.api.tests')
502 504 # register some exception handling view
503 505 config.add_view(exception_view, context=JSONRPCBaseError)
504 506 config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
505 507 config.add_notfound_view(exception_view, jsonrpc_method_not_found=True)
@@ -1,39 +1,39 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2011-2016 RhodeCode GmbH
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 class JSONRPCBaseError(Exception):
23 23 pass
24 24
25 25
26 26 class JSONRPCError(JSONRPCBaseError):
27 27 pass
28 28
29 29
30 30 class JSONRPCValidationError(JSONRPCBaseError):
31 31
32 32 def __init__(self, *args, **kwargs):
33 33 self.colander_exception = kwargs.pop('colander_exc')
34 34 super(JSONRPCValidationError, self).__init__(*args, **kwargs)
35 35
36 36
37 37 class JSONRPCForbidden(JSONRPCBaseError):
38 38 pass
39 39
@@ -1,19 +1,19 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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/
@@ -1,42 +1,42 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.meta import Session
24 24 from rhodecode.model.user import UserModel
25 25 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
26 26
27 27
28 28 @pytest.fixture(scope="class")
29 29 def testuser_api(request, pylonsapp):
30 30 cls = request.cls
31 31 cls.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
32 32 cls.apikey = cls.usr.api_key
33 33 cls.test_user = UserModel().create_or_update(
34 34 username='test-api',
35 35 password='test',
36 36 email='test@api.rhodecode.org',
37 37 firstname='first',
38 38 lastname='last'
39 39 )
40 40 Session().commit()
41 41 cls.TEST_USER_LOGIN = cls.test_user.username
42 42 cls.apikey_regular = cls.test_user.api_key
@@ -1,62 +1,62 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.db import Repository, RepositoryField
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_ok, assert_error)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestAddFieldToRepo(object):
30 30 def test_api_add_field_to_repo(self, backend):
31 31 repo = backend.create_repo()
32 32 repo_name = repo.repo_name
33 33 id_, params = build_data(
34 34 self.apikey, 'add_field_to_repo',
35 35 repoid=repo_name,
36 36 key='extra_field',
37 37 label='extra_field_label',
38 38 description='extra_field_desc')
39 39 response = api_call(self.app, params)
40 40 expected = {
41 41 'msg': 'Added new repository field `extra_field`',
42 42 'success': True,
43 43 }
44 44 assert_ok(id_, expected, given=response.body)
45 45
46 46 repo = Repository.get_by_repo_name(repo_name)
47 47 repo_field = RepositoryField.get_by_key_name('extra_field', repo)
48 48 _data = repo_field.get_dict()
49 49 assert _data['field_desc'] == 'extra_field_desc'
50 50 assert _data['field_key'] == 'extra_field'
51 51 assert _data['field_label'] == 'extra_field_label'
52 52
53 53 id_, params = build_data(
54 54 self.apikey, 'add_field_to_repo',
55 55 repoid=repo_name,
56 56 key='extra_field',
57 57 label='extra_field_label',
58 58 description='extra_field_desc')
59 59 response = api_call(self.app, params)
60 60 expected = 'Field with key `extra_field` exists for repo `%s`' % (
61 61 repo_name)
62 62 assert_error(id_, expected, given=response.body)
@@ -1,72 +1,72 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.user_group import UserGroupModel
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_error, assert_ok, crash)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestAddUserToUserGroup(object):
31 31 def test_api_add_user_to_user_group(self, user_util):
32 32 group = user_util.create_user_group()
33 33 user = user_util.create_user()
34 34 group_name = group.users_group_name
35 35 user_name = user.username
36 36 id_, params = build_data(
37 37 self.apikey, 'add_user_to_user_group',
38 38 usergroupid=group_name, userid=user_name)
39 39 response = api_call(self.app, params)
40 40 expected = {
41 41 'msg': 'added member `%s` to user group `%s`' % (
42 42 user_name, group_name
43 43 ),
44 44 'success': True
45 45 }
46 46 assert_ok(id_, expected, given=response.body)
47 47
48 48 def test_api_add_user_to_user_group_that_doesnt_exist(self, user_util):
49 49 user = user_util.create_user()
50 50 user_name = user.username
51 51 id_, params = build_data(
52 52 self.apikey, 'add_user_to_user_group',
53 53 usergroupid='false-group',
54 54 userid=user_name)
55 55 response = api_call(self.app, params)
56 56
57 57 expected = 'user group `%s` does not exist' % 'false-group'
58 58 assert_error(id_, expected, given=response.body)
59 59
60 60 @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
61 61 def test_api_add_user_to_user_group_exception_occurred(self, user_util):
62 62 group = user_util.create_user_group()
63 63 user = user_util.create_user()
64 64 group_name = group.users_group_name
65 65 user_name = user.username
66 66 id_, params = build_data(
67 67 self.apikey, 'add_user_to_user_group',
68 68 usergroupid=group_name, userid=user_name)
69 69 response = api_call(self.app, params)
70 70
71 71 expected = 'failed to add member to user group `%s`' % (group_name,)
72 72 assert_error(id_, expected, given=response.body)
@@ -1,125 +1,125 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.api.utils import Optional, OAttr
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_error, assert_ok)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestApi(object):
30 30 maxDiff = None
31 31
32 32 def test_Optional_object(self):
33 33
34 34 option1 = Optional(None)
35 35 assert '<Optional:%s>' % (None,) == repr(option1)
36 36 assert option1() is None
37 37
38 38 assert 1 == Optional.extract(Optional(1))
39 39 assert 'example' == Optional.extract('example')
40 40
41 41 def test_Optional_OAttr(self):
42 42 option1 = Optional(OAttr('apiuser'))
43 43 assert 'apiuser' == Optional.extract(option1)
44 44
45 45 def test_OAttr_object(self):
46 46 oattr1 = OAttr('apiuser')
47 47 assert '<OptionalAttr:apiuser>' == repr(oattr1)
48 48 assert oattr1() == oattr1
49 49
50 50 def test_api_wrong_key(self):
51 51 id_, params = build_data('trololo', 'get_user')
52 52 response = api_call(self.app, params)
53 53
54 54 expected = 'Invalid API KEY'
55 55 assert_error(id_, expected, given=response.body)
56 56
57 57 def test_api_missing_non_optional_param(self):
58 58 id_, params = build_data(self.apikey, 'get_repo')
59 59 response = api_call(self.app, params)
60 60
61 61 expected = 'Missing non optional `repoid` arg in JSON DATA'
62 62 assert_error(id_, expected, given=response.body)
63 63
64 64 def test_api_missing_non_optional_param_args_null(self):
65 65 id_, params = build_data(self.apikey, 'get_repo')
66 66 params = params.replace('"args": {}', '"args": null')
67 67 response = api_call(self.app, params)
68 68
69 69 expected = 'Missing non optional `repoid` arg in JSON DATA'
70 70 assert_error(id_, expected, given=response.body)
71 71
72 72 def test_api_missing_non_optional_param_args_bad(self):
73 73 id_, params = build_data(self.apikey, 'get_repo')
74 74 params = params.replace('"args": {}', '"args": 1')
75 75 response = api_call(self.app, params)
76 76
77 77 expected = 'Missing non optional `repoid` arg in JSON DATA'
78 78 assert_error(id_, expected, given=response.body)
79 79
80 80 def test_api_non_existing_method(self, request):
81 81 id_, params = build_data(self.apikey, 'not_existing', args='xx')
82 82 response = api_call(self.app, params)
83 83 expected = 'No such method: not_existing'
84 84 assert_error(id_, expected, given=response.body)
85 85
86 86 def test_api_disabled_user(self, request):
87 87
88 88 def set_active(active):
89 89 from rhodecode.model.db import Session, User
90 90 user = User.get_by_auth_token(self.apikey)
91 91 user.active = active
92 92 Session().add(user)
93 93 Session().commit()
94 94
95 95 request.addfinalizer(lambda: set_active(True))
96 96
97 97 set_active(False)
98 98 id_, params = build_data(self.apikey, 'test', args='xx')
99 99 response = api_call(self.app, params)
100 100 expected = 'Request from this user not allowed'
101 101 assert_error(id_, expected, given=response.body)
102 102
103 103 def test_api_args_is_null(self):
104 104 __, params = build_data(self.apikey, 'get_users', )
105 105 params = params.replace('"args": {}', '"args": null')
106 106 response = api_call(self.app, params)
107 107 assert response.status == '200 OK'
108 108
109 109 def test_api_args_is_bad(self):
110 110 __, params = build_data(self.apikey, 'get_users', )
111 111 params = params.replace('"args": {}', '"args": 1')
112 112 response = api_call(self.app, params)
113 113 assert response.status == '200 OK'
114 114
115 115 def test_api_args_different_args(self):
116 116 import string
117 117 expected = {
118 118 'ascii_letters': string.ascii_letters,
119 119 'ws': string.whitespace,
120 120 'printables': string.printable
121 121 }
122 122 id_, params = build_data(self.apikey, 'test', args=expected)
123 123 response = api_call(self.app, params)
124 124 assert response.status == '200 OK'
125 125 assert_ok(id_, expected, response.body)
@@ -1,111 +1,111 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.db import UserLog
24 24 from rhodecode.model.pull_request import PullRequestModel
25 25 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_error, assert_ok)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestClosePullRequest(object):
32 32 @pytest.mark.backends("git", "hg")
33 33 def test_api_close_pull_request(self, pr_util):
34 34 pull_request = pr_util.create_pull_request()
35 35 pull_request_id = pull_request.pull_request_id
36 36 author = pull_request.user_id
37 37 repo = pull_request.target_repo.repo_id
38 38 id_, params = build_data(
39 39 self.apikey, 'close_pull_request',
40 40 repoid=pull_request.target_repo.repo_name,
41 41 pullrequestid=pull_request.pull_request_id)
42 42 response = api_call(self.app, params)
43 43 expected = {
44 44 'pull_request_id': pull_request_id,
45 45 'closed': True,
46 46 }
47 47 assert_ok(id_, expected, response.body)
48 48 action = 'user_closed_pull_request:%d' % pull_request_id
49 49 journal = UserLog.query()\
50 50 .filter(UserLog.user_id == author)\
51 51 .filter(UserLog.repository_id == repo)\
52 52 .filter(UserLog.action == action)\
53 53 .all()
54 54 assert len(journal) == 1
55 55
56 56 @pytest.mark.backends("git", "hg")
57 57 def test_api_close_pull_request_already_closed_error(self, pr_util):
58 58 pull_request = pr_util.create_pull_request()
59 59 pull_request_id = pull_request.pull_request_id
60 60 pull_request_repo = pull_request.target_repo.repo_name
61 61 PullRequestModel().close_pull_request(
62 62 pull_request, pull_request.author)
63 63 id_, params = build_data(
64 64 self.apikey, 'close_pull_request',
65 65 repoid=pull_request_repo, pullrequestid=pull_request_id)
66 66 response = api_call(self.app, params)
67 67
68 68 expected = 'pull request `%s` is already closed' % pull_request_id
69 69 assert_error(id_, expected, given=response.body)
70 70
71 71 @pytest.mark.backends("git", "hg")
72 72 def test_api_close_pull_request_repo_error(self):
73 73 id_, params = build_data(
74 74 self.apikey, 'close_pull_request',
75 75 repoid=666, pullrequestid=1)
76 76 response = api_call(self.app, params)
77 77
78 78 expected = 'repository `666` does not exist'
79 79 assert_error(id_, expected, given=response.body)
80 80
81 81 @pytest.mark.backends("git", "hg")
82 82 def test_api_close_pull_request_non_admin_with_userid_error(self,
83 83 pr_util):
84 84 pull_request = pr_util.create_pull_request()
85 85 id_, params = build_data(
86 86 self.apikey_regular, 'close_pull_request',
87 87 repoid=pull_request.target_repo.repo_name,
88 88 pullrequestid=pull_request.pull_request_id,
89 89 userid=TEST_USER_ADMIN_LOGIN)
90 90 response = api_call(self.app, params)
91 91
92 92 expected = 'userid is not the same as your user'
93 93 assert_error(id_, expected, given=response.body)
94 94
95 95 @pytest.mark.backends("git", "hg")
96 96 def test_api_close_pull_request_no_perms_to_close(
97 97 self, user_util, pr_util):
98 98 user = user_util.create_user()
99 99 pull_request = pr_util.create_pull_request()
100 100
101 101 id_, params = build_data(
102 102 user.api_key, 'close_pull_request',
103 103 repoid=pull_request.target_repo.repo_name,
104 104 pullrequestid=pull_request.pull_request_id,)
105 105 response = api_call(self.app, params)
106 106
107 107 expected = ('pull request `%s` close failed, '
108 108 'no permission to close.') % pull_request.pull_request_id
109 109
110 110 response_json = response.json['error']
111 111 assert response_json == expected
@@ -1,58 +1,58 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.db import ChangesetStatus
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_error, assert_ok)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestCommentCommit(object):
30 30 def test_api_comment_commit_on_empty_repo(self, backend):
31 31 repo = backend.create_repo()
32 32 id_, params = build_data(
33 33 self.apikey, 'comment_commit', repoid=repo.repo_name,
34 34 commit_id='tip', message='message', status_change=None)
35 35 response = api_call(self.app, params)
36 36 expected = 'failed to set comment on repository `%s`' % repo.repo_name
37 37 assert_error(id_, expected, given=response.body)
38 38
39 39 @pytest.mark.parametrize("status_change, message, commit_id", [
40 40 (None, 'Hallo', 'tip'),
41 41 (ChangesetStatus.STATUS_APPROVED, 'Approved', 'tip'),
42 42 (ChangesetStatus.STATUS_REJECTED, 'Rejected', 'tip'),
43 43 ])
44 44 def test_api_comment_commit(
45 45 self, backend, status_change, message, commit_id,
46 46 no_notifications):
47 47 id_, params = build_data(
48 48 self.apikey, 'comment_commit', repoid=backend.repo_name,
49 49 commit_id=commit_id, message=message, status=status_change)
50 50 response = api_call(self.app, params)
51 51 repo = backend.repo.scm_instance()
52 52 expected = {
53 53 'msg': 'Commented on commit `%s` for repository `%s`' % (
54 54 repo.get_changeset().raw_id, backend.repo_name),
55 55 'status_change': status_change,
56 56 'success': True
57 57 }
58 58 assert_ok(id_, expected, given=response.body)
@@ -1,146 +1,209 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 from rhodecode.model.comment import ChangesetCommentsModel
23 from rhodecode.model.comment import CommentsModel
24 24 from rhodecode.model.db import UserLog
25 25 from rhodecode.model.pull_request import PullRequestModel
26 26 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
27 27 from rhodecode.api.tests.utils import (
28 28 build_data, api_call, assert_error, assert_ok)
29 29
30 30
31 31 @pytest.mark.usefixtures("testuser_api", "app")
32 32 class TestCommentPullRequest(object):
33 33 finalizers = []
34 34
35 35 def teardown_method(self, method):
36 36 if self.finalizers:
37 37 for finalizer in self.finalizers:
38 38 finalizer()
39 39 self.finalizers = []
40 40
41 41 @pytest.mark.backends("git", "hg")
42 42 def test_api_comment_pull_request(self, pr_util, no_notifications):
43 43 pull_request = pr_util.create_pull_request()
44 44 pull_request_id = pull_request.pull_request_id
45 45 author = pull_request.user_id
46 46 repo = pull_request.target_repo.repo_id
47 47 id_, params = build_data(
48 48 self.apikey, 'comment_pull_request',
49 49 repoid=pull_request.target_repo.repo_name,
50 50 pullrequestid=pull_request.pull_request_id,
51 51 message='test message')
52 52 response = api_call(self.app, params)
53 53 pull_request = PullRequestModel().get(pull_request.pull_request_id)
54 54
55 comments = ChangesetCommentsModel().get_comments(
55 comments = CommentsModel().get_comments(
56 56 pull_request.target_repo.repo_id, pull_request=pull_request)
57 57
58 58 expected = {
59 59 'pull_request_id': pull_request.pull_request_id,
60 60 'comment_id': comments[-1].comment_id,
61 'status': None
61 'status': {'given': None, 'was_changed': None}
62 62 }
63 63 assert_ok(id_, expected, response.body)
64 64
65 65 action = 'user_commented_pull_request:%d' % pull_request_id
66 66 journal = UserLog.query()\
67 67 .filter(UserLog.user_id == author)\
68 68 .filter(UserLog.repository_id == repo)\
69 69 .filter(UserLog.action == action)\
70 70 .all()
71 71 assert len(journal) == 2
72 72
73 73 @pytest.mark.backends("git", "hg")
74 74 def test_api_comment_pull_request_change_status(
75 75 self, pr_util, no_notifications):
76 76 pull_request = pr_util.create_pull_request()
77 77 pull_request_id = pull_request.pull_request_id
78 78 id_, params = build_data(
79 79 self.apikey, 'comment_pull_request',
80 80 repoid=pull_request.target_repo.repo_name,
81 81 pullrequestid=pull_request.pull_request_id,
82 82 status='rejected')
83 83 response = api_call(self.app, params)
84 84 pull_request = PullRequestModel().get(pull_request_id)
85 85
86 comments = ChangesetCommentsModel().get_comments(
86 comments = CommentsModel().get_comments(
87 87 pull_request.target_repo.repo_id, pull_request=pull_request)
88 88 expected = {
89 89 'pull_request_id': pull_request.pull_request_id,
90 90 'comment_id': comments[-1].comment_id,
91 'status': 'rejected'
91 'status': {'given': 'rejected', 'was_changed': True}
92 }
93 assert_ok(id_, expected, response.body)
94
95 @pytest.mark.backends("git", "hg")
96 def test_api_comment_pull_request_change_status_with_specific_commit_id(
97 self, pr_util, no_notifications):
98 pull_request = pr_util.create_pull_request()
99 pull_request_id = pull_request.pull_request_id
100 latest_commit_id = 'test_commit'
101 # inject additional revision, to fail test the status change on
102 # non-latest commit
103 pull_request.revisions = pull_request.revisions + ['test_commit']
104
105 id_, params = build_data(
106 self.apikey, 'comment_pull_request',
107 repoid=pull_request.target_repo.repo_name,
108 pullrequestid=pull_request.pull_request_id,
109 status='approved', commit_id=latest_commit_id)
110 response = api_call(self.app, params)
111 pull_request = PullRequestModel().get(pull_request_id)
112
113 expected = {
114 'pull_request_id': pull_request.pull_request_id,
115 'comment_id': None,
116 'status': {'given': 'approved', 'was_changed': False}
117 }
118 assert_ok(id_, expected, response.body)
119
120 @pytest.mark.backends("git", "hg")
121 def test_api_comment_pull_request_change_status_with_specific_commit_id(
122 self, pr_util, no_notifications):
123 pull_request = pr_util.create_pull_request()
124 pull_request_id = pull_request.pull_request_id
125 latest_commit_id = pull_request.revisions[0]
126
127 id_, params = build_data(
128 self.apikey, 'comment_pull_request',
129 repoid=pull_request.target_repo.repo_name,
130 pullrequestid=pull_request.pull_request_id,
131 status='approved', commit_id=latest_commit_id)
132 response = api_call(self.app, params)
133 pull_request = PullRequestModel().get(pull_request_id)
134
135 comments = CommentsModel().get_comments(
136 pull_request.target_repo.repo_id, pull_request=pull_request)
137 expected = {
138 'pull_request_id': pull_request.pull_request_id,
139 'comment_id': comments[-1].comment_id,
140 'status': {'given': 'approved', 'was_changed': True}
92 141 }
93 142 assert_ok(id_, expected, response.body)
94 143
95 144 @pytest.mark.backends("git", "hg")
96 145 def test_api_comment_pull_request_missing_params_error(self, pr_util):
97 146 pull_request = pr_util.create_pull_request()
98 147 pull_request_id = pull_request.pull_request_id
99 148 pull_request_repo = pull_request.target_repo.repo_name
100 149 id_, params = build_data(
101 150 self.apikey, 'comment_pull_request',
102 151 repoid=pull_request_repo,
103 152 pullrequestid=pull_request_id)
104 153 response = api_call(self.app, params)
105 154
106 expected = 'message and status parameter missing'
155 expected = 'Both message and status parameters are missing. At least one is required.'
107 156 assert_error(id_, expected, given=response.body)
108 157
109 158 @pytest.mark.backends("git", "hg")
110 159 def test_api_comment_pull_request_unknown_status_error(self, pr_util):
111 160 pull_request = pr_util.create_pull_request()
112 161 pull_request_id = pull_request.pull_request_id
113 162 pull_request_repo = pull_request.target_repo.repo_name
114 163 id_, params = build_data(
115 164 self.apikey, 'comment_pull_request',
116 165 repoid=pull_request_repo,
117 166 pullrequestid=pull_request_id,
118 167 status='42')
119 168 response = api_call(self.app, params)
120 169
121 expected = 'unknown comment status`42`'
170 expected = 'Unknown comment status: `42`'
122 171 assert_error(id_, expected, given=response.body)
123 172
124 173 @pytest.mark.backends("git", "hg")
125 174 def test_api_comment_pull_request_repo_error(self):
126 175 id_, params = build_data(
127 176 self.apikey, 'comment_pull_request',
128 177 repoid=666, pullrequestid=1)
129 178 response = api_call(self.app, params)
130 179
131 180 expected = 'repository `666` does not exist'
132 181 assert_error(id_, expected, given=response.body)
133 182
134 183 @pytest.mark.backends("git", "hg")
135 184 def test_api_comment_pull_request_non_admin_with_userid_error(
136 185 self, pr_util):
137 186 pull_request = pr_util.create_pull_request()
138 187 id_, params = build_data(
139 188 self.apikey_regular, 'comment_pull_request',
140 189 repoid=pull_request.target_repo.repo_name,
141 190 pullrequestid=pull_request.pull_request_id,
142 191 userid=TEST_USER_ADMIN_LOGIN)
143 192 response = api_call(self.app, params)
144 193
145 194 expected = 'userid is not the same as your user'
146 195 assert_error(id_, expected, given=response.body)
196
197 @pytest.mark.backends("git", "hg")
198 def test_api_comment_pull_request_wrong_commit_id_error(self, pr_util):
199 pull_request = pr_util.create_pull_request()
200 id_, params = build_data(
201 self.apikey_regular, 'comment_pull_request',
202 repoid=pull_request.target_repo.repo_name,
203 status='approved',
204 pullrequestid=pull_request.pull_request_id,
205 commit_id='XXX')
206 response = api_call(self.app, params)
207
208 expected = 'Invalid commit_id `XXX` for this pull request.'
209 assert_error(id_, expected, given=response.body)
@@ -1,102 +1,102 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.db import Gist
25 25 from rhodecode.model.gist import GistModel
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_error, assert_ok, crash)
28 28 from rhodecode.tests.fixture import Fixture
29 29
30 30
31 31 @pytest.mark.usefixtures("testuser_api", "app")
32 32 class TestApiCreateGist(object):
33 33 @pytest.mark.parametrize("lifetime, gist_type, gist_acl_level", [
34 34 (10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC),
35 35 (20, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PRIVATE),
36 36 (40, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PUBLIC),
37 37 (80, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PRIVATE),
38 38 ])
39 39 def test_api_create_gist(self, lifetime, gist_type, gist_acl_level):
40 40 id_, params = build_data(
41 41 self.apikey_regular, 'create_gist',
42 42 lifetime=lifetime,
43 43 description='foobar-gist',
44 44 gist_type=gist_type,
45 45 acl_level=gist_acl_level,
46 46 files={'foobar_ąć': {'content': 'foo'}})
47 47 response = api_call(self.app, params)
48 48 response_json = response.json
49 49 gist = response_json['result']['gist']
50 50 expected = {
51 51 'gist': {
52 52 'access_id': gist['access_id'],
53 53 'created_on': gist['created_on'],
54 54 'modified_at': gist['modified_at'],
55 55 'description': 'foobar-gist',
56 56 'expires': gist['expires'],
57 57 'gist_id': gist['gist_id'],
58 58 'type': gist_type,
59 59 'url': gist['url'],
60 60 # content is empty since we don't show it here
61 61 'content': None,
62 62 'acl_level': gist_acl_level,
63 63 },
64 64 'msg': 'created new gist'
65 65 }
66 66 try:
67 67 assert_ok(id_, expected, given=response.body)
68 68 finally:
69 69 Fixture().destroy_gists()
70 70
71 71 @pytest.mark.parametrize("expected, lifetime, gist_type, gist_acl_level, files", [
72 72 ({'gist_type': '"ups" is not one of private, public'},
73 73 10, 'ups', Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}),
74 74
75 75 ({'lifetime': '-120 is less than minimum value -1'},
76 76 -120, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}),
77 77
78 78 ({'0.content': 'Required'},
79 79 10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'x': 'f'}}),
80 80 ])
81 81 def test_api_try_create_gist(
82 82 self, expected, lifetime, gist_type, gist_acl_level, files):
83 83 id_, params = build_data(
84 84 self.apikey_regular, 'create_gist',
85 85 lifetime=lifetime,
86 86 description='foobar-gist',
87 87 gist_type=gist_type,
88 88 acl_level=gist_acl_level,
89 89 files=files)
90 90 response = api_call(self.app, params)
91 91
92 92 try:
93 93 assert_error(id_, expected, given=response.body)
94 94 finally:
95 95 Fixture().destroy_gists()
96 96
97 97 @mock.patch.object(GistModel, 'create', crash)
98 98 def test_api_create_gist_exception_occurred(self):
99 99 id_, params = build_data(self.apikey_regular, 'create_gist', files={})
100 100 response = api_call(self.app, params)
101 101 expected = 'failed to create gist'
102 102 assert_error(id_, expected, given=response.body)
@@ -1,279 +1,279 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.db import User
24 24 from rhodecode.model.pull_request import PullRequestModel
25 25 from rhodecode.model.repo import RepoModel
26 26 from rhodecode.model.user import UserModel
27 27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN
28 28 from rhodecode.api.tests.utils import build_data, api_call, assert_error
29 29
30 30
31 31 @pytest.mark.usefixtures("testuser_api", "app")
32 32 class TestCreatePullRequestApi(object):
33 33 finalizers = []
34 34
35 35 def teardown_method(self, method):
36 36 if self.finalizers:
37 37 for finalizer in self.finalizers:
38 38 finalizer()
39 39 self.finalizers = []
40 40
41 41 def test_create_with_wrong_data(self):
42 42 required_data = {
43 43 'source_repo': 'tests/source_repo',
44 44 'target_repo': 'tests/target_repo',
45 45 'source_ref': 'branch:default:initial',
46 46 'target_ref': 'branch:default:new-feature',
47 47 'title': 'Test PR 1'
48 48 }
49 49 for key in required_data:
50 50 data = required_data.copy()
51 51 data.pop(key)
52 52 id_, params = build_data(
53 53 self.apikey, 'create_pull_request', **data)
54 54 response = api_call(self.app, params)
55 55
56 56 expected = 'Missing non optional `{}` arg in JSON DATA'.format(key)
57 57 assert_error(id_, expected, given=response.body)
58 58
59 59 @pytest.mark.backends("git", "hg")
60 60 def test_create_with_correct_data(self, backend):
61 61 data = self._prepare_data(backend)
62 62 RepoModel().revoke_user_permission(
63 63 self.source.repo_name, User.DEFAULT_USER)
64 64 id_, params = build_data(
65 65 self.apikey_regular, 'create_pull_request', **data)
66 66 response = api_call(self.app, params)
67 67 expected_message = "Created new pull request `{title}`".format(
68 68 title=data['title'])
69 69 result = response.json
70 70 assert result['result']['msg'] == expected_message
71 71 pull_request_id = result['result']['pull_request_id']
72 72 pull_request = PullRequestModel().get(pull_request_id)
73 73 assert pull_request.title == data['title']
74 74 assert pull_request.description == data['description']
75 75 assert pull_request.source_ref == data['source_ref']
76 76 assert pull_request.target_ref == data['target_ref']
77 77 assert pull_request.source_repo.repo_name == data['source_repo']
78 78 assert pull_request.target_repo.repo_name == data['target_repo']
79 79 assert pull_request.revisions == [self.commit_ids['change']]
80 80 assert pull_request.reviewers == []
81 81
82 82 @pytest.mark.backends("git", "hg")
83 83 def test_create_with_empty_description(self, backend):
84 84 data = self._prepare_data(backend)
85 85 data.pop('description')
86 86 id_, params = build_data(
87 87 self.apikey_regular, 'create_pull_request', **data)
88 88 response = api_call(self.app, params)
89 89 expected_message = "Created new pull request `{title}`".format(
90 90 title=data['title'])
91 91 result = response.json
92 92 assert result['result']['msg'] == expected_message
93 93 pull_request_id = result['result']['pull_request_id']
94 94 pull_request = PullRequestModel().get(pull_request_id)
95 95 assert pull_request.description == ''
96 96
97 97 @pytest.mark.backends("git", "hg")
98 98 def test_create_with_reviewers_specified_by_names(
99 99 self, backend, no_notifications):
100 100 data = self._prepare_data(backend)
101 101 reviewers = [TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN]
102 102 data['reviewers'] = reviewers
103 103 id_, params = build_data(
104 104 self.apikey_regular, 'create_pull_request', **data)
105 105 response = api_call(self.app, params)
106 106
107 107 expected_message = "Created new pull request `{title}`".format(
108 108 title=data['title'])
109 109 result = response.json
110 110 assert result['result']['msg'] == expected_message
111 111 pull_request_id = result['result']['pull_request_id']
112 112 pull_request = PullRequestModel().get(pull_request_id)
113 113 actual_reviewers = [r.user.username for r in pull_request.reviewers]
114 114 assert sorted(actual_reviewers) == sorted(reviewers)
115 115
116 116 @pytest.mark.backends("git", "hg")
117 117 def test_create_with_reviewers_specified_by_ids(
118 118 self, backend, no_notifications):
119 119 data = self._prepare_data(backend)
120 120 reviewer_names = [TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN]
121 121 reviewers = [
122 122 UserModel().get_by_username(n).user_id for n in reviewer_names]
123 123 data['reviewers'] = reviewers
124 124 id_, params = build_data(
125 125 self.apikey_regular, 'create_pull_request', **data)
126 126 response = api_call(self.app, params)
127 127
128 128 expected_message = "Created new pull request `{title}`".format(
129 129 title=data['title'])
130 130 result = response.json
131 131 assert result['result']['msg'] == expected_message
132 132 pull_request_id = result['result']['pull_request_id']
133 133 pull_request = PullRequestModel().get(pull_request_id)
134 134 actual_reviewers = [r.user.username for r in pull_request.reviewers]
135 135 assert sorted(actual_reviewers) == sorted(reviewer_names)
136 136
137 137 @pytest.mark.backends("git", "hg")
138 138 def test_create_fails_when_the_reviewer_is_not_found(self, backend):
139 139 data = self._prepare_data(backend)
140 140 reviewers = ['somebody']
141 141 data['reviewers'] = reviewers
142 142 id_, params = build_data(
143 143 self.apikey_regular, 'create_pull_request', **data)
144 144 response = api_call(self.app, params)
145 145 expected_message = 'user `somebody` does not exist'
146 146 assert_error(id_, expected_message, given=response.body)
147 147
148 148 @pytest.mark.backends("git", "hg")
149 149 def test_cannot_create_with_reviewers_in_wrong_format(self, backend):
150 150 data = self._prepare_data(backend)
151 151 reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN])
152 152 data['reviewers'] = reviewers
153 153 id_, params = build_data(
154 154 self.apikey_regular, 'create_pull_request', **data)
155 155 response = api_call(self.app, params)
156 156 expected_message = 'reviewers should be specified as a list'
157 157 assert_error(id_, expected_message, given=response.body)
158 158
159 159 @pytest.mark.backends("git", "hg")
160 160 def test_create_with_no_commit_hashes(self, backend):
161 161 data = self._prepare_data(backend)
162 162 expected_source_ref = data['source_ref']
163 163 expected_target_ref = data['target_ref']
164 164 data['source_ref'] = 'branch:{}'.format(backend.default_branch_name)
165 165 data['target_ref'] = 'branch:{}'.format(backend.default_branch_name)
166 166 id_, params = build_data(
167 167 self.apikey_regular, 'create_pull_request', **data)
168 168 response = api_call(self.app, params)
169 169 expected_message = "Created new pull request `{title}`".format(
170 170 title=data['title'])
171 171 result = response.json
172 172 assert result['result']['msg'] == expected_message
173 173 pull_request_id = result['result']['pull_request_id']
174 174 pull_request = PullRequestModel().get(pull_request_id)
175 175 assert pull_request.source_ref == expected_source_ref
176 176 assert pull_request.target_ref == expected_target_ref
177 177
178 178 @pytest.mark.backends("git", "hg")
179 179 @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"])
180 180 def test_create_fails_with_wrong_repo(self, backend, data_key):
181 181 repo_name = 'fake-repo'
182 182 data = self._prepare_data(backend)
183 183 data[data_key] = repo_name
184 184 id_, params = build_data(
185 185 self.apikey_regular, 'create_pull_request', **data)
186 186 response = api_call(self.app, params)
187 187 expected_message = 'repository `{}` does not exist'.format(repo_name)
188 188 assert_error(id_, expected_message, given=response.body)
189 189
190 190 @pytest.mark.backends("git", "hg")
191 191 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
192 192 def test_create_fails_with_non_existing_branch(self, backend, data_key):
193 193 branch_name = 'test-branch'
194 194 data = self._prepare_data(backend)
195 195 data[data_key] = "branch:{}".format(branch_name)
196 196 id_, params = build_data(
197 197 self.apikey_regular, 'create_pull_request', **data)
198 198 response = api_call(self.app, params)
199 199 expected_message = 'The specified branch `{}` does not exist'.format(
200 200 branch_name)
201 201 assert_error(id_, expected_message, given=response.body)
202 202
203 203 @pytest.mark.backends("git", "hg")
204 204 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
205 205 def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key):
206 206 data = self._prepare_data(backend)
207 207 ref = 'stange-ref'
208 208 data[data_key] = ref
209 209 id_, params = build_data(
210 210 self.apikey_regular, 'create_pull_request', **data)
211 211 response = api_call(self.app, params)
212 212 expected_message = (
213 213 'Ref `{ref}` given in a wrong format. Please check the API'
214 214 ' documentation for more details'.format(ref=ref))
215 215 assert_error(id_, expected_message, given=response.body)
216 216
217 217 @pytest.mark.backends("git", "hg")
218 218 @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"])
219 219 def test_create_fails_with_non_existing_ref(self, backend, data_key):
220 220 commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10'
221 221 ref = self._get_full_ref(backend, commit_id)
222 222 data = self._prepare_data(backend)
223 223 data[data_key] = ref
224 224 id_, params = build_data(
225 225 self.apikey_regular, 'create_pull_request', **data)
226 226 response = api_call(self.app, params)
227 227 expected_message = 'Ref `{}` does not exist'.format(ref)
228 228 assert_error(id_, expected_message, given=response.body)
229 229
230 230 @pytest.mark.backends("git", "hg")
231 231 def test_create_fails_when_no_revisions(self, backend):
232 232 data = self._prepare_data(backend, source_head='initial')
233 233 id_, params = build_data(
234 234 self.apikey_regular, 'create_pull_request', **data)
235 235 response = api_call(self.app, params)
236 236 expected_message = 'no commits found'
237 237 assert_error(id_, expected_message, given=response.body)
238 238
239 239 @pytest.mark.backends("git", "hg")
240 240 def test_create_fails_when_no_permissions(self, backend):
241 241 data = self._prepare_data(backend)
242 242 RepoModel().revoke_user_permission(
243 243 self.source.repo_name, User.DEFAULT_USER)
244 244 RepoModel().revoke_user_permission(
245 245 self.source.repo_name, self.test_user)
246 246 id_, params = build_data(
247 247 self.apikey_regular, 'create_pull_request', **data)
248 248 response = api_call(self.app, params)
249 249 expected_message = 'repository `{}` does not exist'.format(
250 250 self.source.repo_name)
251 251 assert_error(id_, expected_message, given=response.body)
252 252
253 253 def _prepare_data(
254 254 self, backend, source_head='change', target_head='initial'):
255 255 commits = [
256 256 {'message': 'initial'},
257 257 {'message': 'change'},
258 258 {'message': 'new-feature', 'parents': ['initial']},
259 259 ]
260 260 self.commit_ids = backend.create_master_repo(commits)
261 261 self.source = backend.create_repo(heads=[source_head])
262 262 self.target = backend.create_repo(heads=[target_head])
263 263 data = {
264 264 'source_repo': self.source.repo_name,
265 265 'target_repo': self.target.repo_name,
266 266 'source_ref': self._get_full_ref(
267 267 backend, self.commit_ids[source_head]),
268 268 'target_ref': self._get_full_ref(
269 269 backend, self.commit_ids[target_head]),
270 270 'title': 'Test PR 1',
271 271 'description': 'Test'
272 272 }
273 273 RepoModel().grant_user_permission(
274 274 self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read')
275 275 return data
276 276
277 277 def _get_full_ref(self, backend, commit_id):
278 278 return 'branch:{branch}:{commit_id}'.format(
279 279 branch=backend.default_branch_name, commit_id=commit_id)
@@ -1,350 +1,350 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import json
22 22
23 23 import mock
24 24 import pytest
25 25
26 26 from rhodecode.lib.utils2 import safe_unicode
27 27 from rhodecode.lib.vcs import settings
28 28 from rhodecode.model.meta import Session
29 29 from rhodecode.model.repo import RepoModel
30 30 from rhodecode.model.user import UserModel
31 31 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
32 32 from rhodecode.api.tests.utils import (
33 33 build_data, api_call, assert_ok, assert_error, crash)
34 34 from rhodecode.tests.fixture import Fixture
35 35
36 36
37 37 fixture = Fixture()
38 38
39 39
40 40 @pytest.mark.usefixtures("testuser_api", "app")
41 41 class TestCreateRepo(object):
42 42
43 43 @pytest.mark.parametrize('given, expected_name, expected_exc', [
44 44 ('api repo-1', 'api-repo-1', False),
45 45 ('api-repo 1-ąć', 'api-repo-1-ąć', False),
46 46 (u'unicode-ąć', u'unicode-ąć', False),
47 47 ('some repo v1.2', 'some-repo-v1.2', False),
48 48 ('v2.0', 'v2.0', False),
49 49 ])
50 50 def test_api_create_repo(self, backend, given, expected_name, expected_exc):
51 51
52 52 id_, params = build_data(
53 53 self.apikey,
54 54 'create_repo',
55 55 repo_name=given,
56 56 owner=TEST_USER_ADMIN_LOGIN,
57 57 repo_type=backend.alias,
58 58 )
59 59 response = api_call(self.app, params)
60 60
61 61 ret = {
62 62 'msg': 'Created new repository `%s`' % (expected_name,),
63 63 'success': True,
64 64 'task': None,
65 65 }
66 66 expected = ret
67 67 assert_ok(id_, expected, given=response.body)
68 68
69 69 repo = RepoModel().get_by_repo_name(safe_unicode(expected_name))
70 70 assert repo is not None
71 71
72 72 id_, params = build_data(self.apikey, 'get_repo', repoid=expected_name)
73 73 response = api_call(self.app, params)
74 74 body = json.loads(response.body)
75 75
76 76 assert body['result']['enable_downloads'] is False
77 77 assert body['result']['enable_locking'] is False
78 78 assert body['result']['enable_statistics'] is False
79 79
80 80 fixture.destroy_repo(safe_unicode(expected_name))
81 81
82 82 def test_api_create_restricted_repo_type(self, backend):
83 83 repo_name = 'api-repo-type-{0}'.format(backend.alias)
84 84 id_, params = build_data(
85 85 self.apikey,
86 86 'create_repo',
87 87 repo_name=repo_name,
88 88 owner=TEST_USER_ADMIN_LOGIN,
89 89 repo_type=backend.alias,
90 90 )
91 91 git_backend = settings.BACKENDS['git']
92 92 with mock.patch(
93 93 'rhodecode.lib.vcs.settings.BACKENDS', {'git': git_backend}):
94 94 response = api_call(self.app, params)
95 95
96 96 repo = RepoModel().get_by_repo_name(repo_name)
97 97
98 98 if backend.alias == 'git':
99 99 assert repo is not None
100 100 expected = {
101 101 'msg': 'Created new repository `{0}`'.format(repo_name,),
102 102 'success': True,
103 103 'task': None,
104 104 }
105 105 assert_ok(id_, expected, given=response.body)
106 106 else:
107 107 assert repo is None
108 108
109 109 fixture.destroy_repo(repo_name)
110 110
111 111 def test_api_create_repo_with_booleans(self, backend):
112 112 repo_name = 'api-repo-2'
113 113 id_, params = build_data(
114 114 self.apikey,
115 115 'create_repo',
116 116 repo_name=repo_name,
117 117 owner=TEST_USER_ADMIN_LOGIN,
118 118 repo_type=backend.alias,
119 119 enable_statistics=True,
120 120 enable_locking=True,
121 121 enable_downloads=True
122 122 )
123 123 response = api_call(self.app, params)
124 124
125 125 repo = RepoModel().get_by_repo_name(repo_name)
126 126
127 127 assert repo is not None
128 128 ret = {
129 129 'msg': 'Created new repository `%s`' % (repo_name,),
130 130 'success': True,
131 131 'task': None,
132 132 }
133 133 expected = ret
134 134 assert_ok(id_, expected, given=response.body)
135 135
136 136 id_, params = build_data(self.apikey, 'get_repo', repoid=repo_name)
137 137 response = api_call(self.app, params)
138 138 body = json.loads(response.body)
139 139
140 140 assert body['result']['enable_downloads'] is True
141 141 assert body['result']['enable_locking'] is True
142 142 assert body['result']['enable_statistics'] is True
143 143
144 144 fixture.destroy_repo(repo_name)
145 145
146 146 def test_api_create_repo_in_group(self, backend):
147 147 repo_group_name = 'my_gr'
148 148 # create the parent
149 149 fixture.create_repo_group(repo_group_name)
150 150
151 151 repo_name = '%s/api-repo-gr' % (repo_group_name,)
152 152 id_, params = build_data(
153 153 self.apikey, 'create_repo',
154 154 repo_name=repo_name,
155 155 owner=TEST_USER_ADMIN_LOGIN,
156 156 repo_type=backend.alias,)
157 157 response = api_call(self.app, params)
158 158 repo = RepoModel().get_by_repo_name(repo_name)
159 159 assert repo is not None
160 160 assert repo.group is not None
161 161
162 162 ret = {
163 163 'msg': 'Created new repository `%s`' % (repo_name,),
164 164 'success': True,
165 165 'task': None,
166 166 }
167 167 expected = ret
168 168 assert_ok(id_, expected, given=response.body)
169 169 fixture.destroy_repo(repo_name)
170 170 fixture.destroy_repo_group(repo_group_name)
171 171
172 172 def test_create_repo_in_group_that_doesnt_exist(self, backend, user_util):
173 173 repo_group_name = 'fake_group'
174 174
175 175 repo_name = '%s/api-repo-gr' % (repo_group_name,)
176 176 id_, params = build_data(
177 177 self.apikey, 'create_repo',
178 178 repo_name=repo_name,
179 179 owner=TEST_USER_ADMIN_LOGIN,
180 180 repo_type=backend.alias,)
181 181 response = api_call(self.app, params)
182 182
183 183 expected = {'repo_group': 'Repository group `{}` does not exist'.format(
184 184 repo_group_name)}
185 185 assert_error(id_, expected, given=response.body)
186 186
187 187 def test_api_create_repo_unknown_owner(self, backend):
188 188 repo_name = 'api-repo-2'
189 189 owner = 'i-dont-exist'
190 190 id_, params = build_data(
191 191 self.apikey, 'create_repo',
192 192 repo_name=repo_name,
193 193 owner=owner,
194 194 repo_type=backend.alias)
195 195 response = api_call(self.app, params)
196 196 expected = 'user `%s` does not exist' % (owner,)
197 197 assert_error(id_, expected, given=response.body)
198 198
199 199 def test_api_create_repo_dont_specify_owner(self, backend):
200 200 repo_name = 'api-repo-3'
201 201 id_, params = build_data(
202 202 self.apikey, 'create_repo',
203 203 repo_name=repo_name,
204 204 repo_type=backend.alias)
205 205 response = api_call(self.app, params)
206 206
207 207 repo = RepoModel().get_by_repo_name(repo_name)
208 208 assert repo is not None
209 209 ret = {
210 210 'msg': 'Created new repository `%s`' % (repo_name,),
211 211 'success': True,
212 212 'task': None,
213 213 }
214 214 expected = ret
215 215 assert_ok(id_, expected, given=response.body)
216 216 fixture.destroy_repo(repo_name)
217 217
218 218 def test_api_create_repo_by_non_admin(self, backend):
219 219 repo_name = 'api-repo-4'
220 220 id_, params = build_data(
221 221 self.apikey_regular, 'create_repo',
222 222 repo_name=repo_name,
223 223 repo_type=backend.alias)
224 224 response = api_call(self.app, params)
225 225
226 226 repo = RepoModel().get_by_repo_name(repo_name)
227 227 assert repo is not None
228 228 ret = {
229 229 'msg': 'Created new repository `%s`' % (repo_name,),
230 230 'success': True,
231 231 'task': None,
232 232 }
233 233 expected = ret
234 234 assert_ok(id_, expected, given=response.body)
235 235 fixture.destroy_repo(repo_name)
236 236
237 237 def test_api_create_repo_by_non_admin_specify_owner(self, backend):
238 238 repo_name = 'api-repo-5'
239 239 owner = 'i-dont-exist'
240 240 id_, params = build_data(
241 241 self.apikey_regular, 'create_repo',
242 242 repo_name=repo_name,
243 243 repo_type=backend.alias,
244 244 owner=owner)
245 245 response = api_call(self.app, params)
246 246
247 247 expected = 'Only RhodeCode super-admin can specify `owner` param'
248 248 assert_error(id_, expected, given=response.body)
249 249 fixture.destroy_repo(repo_name)
250 250
251 251 def test_api_create_repo_by_non_admin_no_parent_group_perms(self, backend):
252 252 repo_group_name = 'no-access'
253 253 fixture.create_repo_group(repo_group_name)
254 254 repo_name = 'no-access/api-repo'
255 255
256 256 id_, params = build_data(
257 257 self.apikey_regular, 'create_repo',
258 258 repo_name=repo_name,
259 259 repo_type=backend.alias)
260 260 response = api_call(self.app, params)
261 261
262 262 expected = {'repo_group': 'Repository group `{}` does not exist'.format(
263 263 repo_group_name)}
264 264 assert_error(id_, expected, given=response.body)
265 265 fixture.destroy_repo_group(repo_group_name)
266 266 fixture.destroy_repo(repo_name)
267 267
268 268 def test_api_create_repo_non_admin_no_permission_to_create_to_root_level(
269 269 self, backend, user_util):
270 270
271 271 regular_user = user_util.create_user()
272 272 regular_user_api_key = regular_user.api_key
273 273
274 274 usr = UserModel().get_by_username(regular_user.username)
275 275 usr.inherit_default_permissions = False
276 276 Session().add(usr)
277 277
278 278 repo_name = backend.new_repo_name()
279 279 id_, params = build_data(
280 280 regular_user_api_key, 'create_repo',
281 281 repo_name=repo_name,
282 282 repo_type=backend.alias)
283 283 response = api_call(self.app, params)
284 284 expected = {
285 285 "repo_name": "You do not have the permission to "
286 286 "store repositories in the root location."}
287 287 assert_error(id_, expected, given=response.body)
288 288
289 289 def test_api_create_repo_exists(self, backend):
290 290 repo_name = backend.repo_name
291 291 id_, params = build_data(
292 292 self.apikey, 'create_repo',
293 293 repo_name=repo_name,
294 294 owner=TEST_USER_ADMIN_LOGIN,
295 295 repo_type=backend.alias,)
296 296 response = api_call(self.app, params)
297 297 expected = {
298 298 'unique_repo_name': 'Repository with name `{}` already exists'.format(
299 299 repo_name)}
300 300 assert_error(id_, expected, given=response.body)
301 301
302 302 @mock.patch.object(RepoModel, 'create', crash)
303 303 def test_api_create_repo_exception_occurred(self, backend):
304 304 repo_name = 'api-repo-6'
305 305 id_, params = build_data(
306 306 self.apikey, 'create_repo',
307 307 repo_name=repo_name,
308 308 owner=TEST_USER_ADMIN_LOGIN,
309 309 repo_type=backend.alias,)
310 310 response = api_call(self.app, params)
311 311 expected = 'failed to create repository `%s`' % (repo_name,)
312 312 assert_error(id_, expected, given=response.body)
313 313
314 314 @pytest.mark.parametrize('parent_group, dirty_name, expected_name', [
315 315 (None, 'foo bar x', 'foo-bar-x'),
316 316 ('foo', '/foo//bar x', 'foo/bar-x'),
317 317 ('foo-bar', 'foo-bar //bar x', 'foo-bar/bar-x'),
318 318 ])
319 319 def test_create_repo_with_extra_slashes_in_name(
320 320 self, backend, parent_group, dirty_name, expected_name):
321 321
322 322 if parent_group:
323 323 gr = fixture.create_repo_group(parent_group)
324 324 assert gr.group_name == parent_group
325 325
326 326 id_, params = build_data(
327 327 self.apikey, 'create_repo',
328 328 repo_name=dirty_name,
329 329 repo_type=backend.alias,
330 330 owner=TEST_USER_ADMIN_LOGIN,)
331 331 response = api_call(self.app, params)
332 332 expected ={
333 333 "msg": "Created new repository `{}`".format(expected_name),
334 334 "task": None,
335 335 "success": True
336 336 }
337 337 assert_ok(id_, expected, response.body)
338 338
339 339 repo = RepoModel().get_by_repo_name(expected_name)
340 340 assert repo is not None
341 341
342 342 expected = {
343 343 'msg': 'Created new repository `%s`' % (expected_name,),
344 344 'success': True,
345 345 'task': None,
346 346 }
347 347 assert_ok(id_, expected, given=response.body)
348 348 fixture.destroy_repo(expected_name)
349 349 if parent_group:
350 350 fixture.destroy_repo_group(parent_group)
@@ -1,289 +1,289 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.repo_group import RepoGroupModel
26 26 from rhodecode.model.user import UserModel
27 27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
28 28 from rhodecode.api.tests.utils import (
29 29 build_data, api_call, assert_ok, assert_error, crash)
30 30 from rhodecode.tests.fixture import Fixture
31 31
32 32
33 33 fixture = Fixture()
34 34
35 35
36 36 @pytest.mark.usefixtures("testuser_api", "app")
37 37 class TestCreateRepoGroup(object):
38 38 def test_api_create_repo_group(self):
39 39 repo_group_name = 'api-repo-group'
40 40
41 41 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
42 42 assert repo_group is None
43 43
44 44 id_, params = build_data(
45 45 self.apikey, 'create_repo_group',
46 46 group_name=repo_group_name,
47 47 owner=TEST_USER_ADMIN_LOGIN,)
48 48 response = api_call(self.app, params)
49 49
50 50 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
51 51 assert repo_group is not None
52 52 ret = {
53 53 'msg': 'Created new repo group `%s`' % (repo_group_name,),
54 54 'repo_group': repo_group.get_api_data()
55 55 }
56 56 expected = ret
57 57 try:
58 58 assert_ok(id_, expected, given=response.body)
59 59 finally:
60 60 fixture.destroy_repo_group(repo_group_name)
61 61
62 62 def test_api_create_repo_group_in_another_group(self):
63 63 repo_group_name = 'api-repo-group'
64 64
65 65 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
66 66 assert repo_group is None
67 67 # create the parent
68 68 fixture.create_repo_group(repo_group_name)
69 69
70 70 full_repo_group_name = repo_group_name+'/'+repo_group_name
71 71 id_, params = build_data(
72 72 self.apikey, 'create_repo_group',
73 73 group_name=full_repo_group_name,
74 74 owner=TEST_USER_ADMIN_LOGIN,
75 75 copy_permissions=True)
76 76 response = api_call(self.app, params)
77 77
78 78 repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name)
79 79 assert repo_group is not None
80 80 ret = {
81 81 'msg': 'Created new repo group `%s`' % (full_repo_group_name,),
82 82 'repo_group': repo_group.get_api_data()
83 83 }
84 84 expected = ret
85 85 try:
86 86 assert_ok(id_, expected, given=response.body)
87 87 finally:
88 88 fixture.destroy_repo_group(full_repo_group_name)
89 89 fixture.destroy_repo_group(repo_group_name)
90 90
91 91 def test_api_create_repo_group_in_another_group_not_existing(self):
92 92 repo_group_name = 'api-repo-group-no'
93 93
94 94 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
95 95 assert repo_group is None
96 96
97 97 full_repo_group_name = repo_group_name+'/'+repo_group_name
98 98 id_, params = build_data(
99 99 self.apikey, 'create_repo_group',
100 100 group_name=full_repo_group_name,
101 101 owner=TEST_USER_ADMIN_LOGIN,
102 102 copy_permissions=True)
103 103 response = api_call(self.app, params)
104 104 expected = {
105 105 'repo_group':
106 106 'Parent repository group `{}` does not exist'.format(
107 107 repo_group_name)}
108 108 assert_error(id_, expected, given=response.body)
109 109
110 110 def test_api_create_repo_group_that_exists(self):
111 111 repo_group_name = 'api-repo-group'
112 112
113 113 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
114 114 assert repo_group is None
115 115
116 116 fixture.create_repo_group(repo_group_name)
117 117 id_, params = build_data(
118 118 self.apikey, 'create_repo_group',
119 119 group_name=repo_group_name,
120 120 owner=TEST_USER_ADMIN_LOGIN,)
121 121 response = api_call(self.app, params)
122 122 expected = {
123 123 'unique_repo_group_name':
124 124 'Repository group with name `{}` already exists'.format(
125 125 repo_group_name)}
126 126 try:
127 127 assert_error(id_, expected, given=response.body)
128 128 finally:
129 129 fixture.destroy_repo_group(repo_group_name)
130 130
131 131 def test_api_create_repo_group_regular_user_wit_root_location_perms(
132 132 self, user_util):
133 133 regular_user = user_util.create_user()
134 134 regular_user_api_key = regular_user.api_key
135 135
136 136 repo_group_name = 'api-repo-group-by-regular-user'
137 137
138 138 usr = UserModel().get_by_username(regular_user.username)
139 139 usr.inherit_default_permissions = False
140 140 Session().add(usr)
141 141
142 142 UserModel().grant_perm(
143 143 regular_user.username, 'hg.repogroup.create.true')
144 144 Session().commit()
145 145
146 146 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
147 147 assert repo_group is None
148 148
149 149 id_, params = build_data(
150 150 regular_user_api_key, 'create_repo_group',
151 151 group_name=repo_group_name)
152 152 response = api_call(self.app, params)
153 153
154 154 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
155 155 assert repo_group is not None
156 156 expected = {
157 157 'msg': 'Created new repo group `%s`' % (repo_group_name,),
158 158 'repo_group': repo_group.get_api_data()
159 159 }
160 160 try:
161 161 assert_ok(id_, expected, given=response.body)
162 162 finally:
163 163 fixture.destroy_repo_group(repo_group_name)
164 164
165 165 def test_api_create_repo_group_regular_user_with_admin_perms_to_parent(
166 166 self, user_util):
167 167
168 168 repo_group_name = 'api-repo-group-parent'
169 169
170 170 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
171 171 assert repo_group is None
172 172 # create the parent
173 173 fixture.create_repo_group(repo_group_name)
174 174
175 175 # user perms
176 176 regular_user = user_util.create_user()
177 177 regular_user_api_key = regular_user.api_key
178 178
179 179 usr = UserModel().get_by_username(regular_user.username)
180 180 usr.inherit_default_permissions = False
181 181 Session().add(usr)
182 182
183 183 RepoGroupModel().grant_user_permission(
184 184 repo_group_name, regular_user.username, 'group.admin')
185 185 Session().commit()
186 186
187 187 full_repo_group_name = repo_group_name + '/' + repo_group_name
188 188 id_, params = build_data(
189 189 regular_user_api_key, 'create_repo_group',
190 190 group_name=full_repo_group_name)
191 191 response = api_call(self.app, params)
192 192
193 193 repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name)
194 194 assert repo_group is not None
195 195 expected = {
196 196 'msg': 'Created new repo group `{}`'.format(full_repo_group_name),
197 197 'repo_group': repo_group.get_api_data()
198 198 }
199 199 try:
200 200 assert_ok(id_, expected, given=response.body)
201 201 finally:
202 202 fixture.destroy_repo_group(full_repo_group_name)
203 203 fixture.destroy_repo_group(repo_group_name)
204 204
205 205 def test_api_create_repo_group_regular_user_no_permission_to_create_to_root_level(self):
206 206 repo_group_name = 'api-repo-group'
207 207
208 208 id_, params = build_data(
209 209 self.apikey_regular, 'create_repo_group',
210 210 group_name=repo_group_name)
211 211 response = api_call(self.app, params)
212 212
213 213 expected = {
214 214 'repo_group':
215 215 u'You do not have the permission to store '
216 216 u'repository groups in the root location.'}
217 217 assert_error(id_, expected, given=response.body)
218 218
219 219 def test_api_create_repo_group_regular_user_no_parent_group_perms(self):
220 220 repo_group_name = 'api-repo-group-regular-user'
221 221
222 222 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
223 223 assert repo_group is None
224 224 # create the parent
225 225 fixture.create_repo_group(repo_group_name)
226 226
227 227 full_repo_group_name = repo_group_name+'/'+repo_group_name
228 228
229 229 id_, params = build_data(
230 230 self.apikey_regular, 'create_repo_group',
231 231 group_name=full_repo_group_name)
232 232 response = api_call(self.app, params)
233 233
234 234 expected = {
235 235 'repo_group':
236 236 'Parent repository group `{}` does not exist'.format(
237 237 repo_group_name)}
238 238 try:
239 239 assert_error(id_, expected, given=response.body)
240 240 finally:
241 241 fixture.destroy_repo_group(repo_group_name)
242 242
243 243 def test_api_create_repo_group_regular_user_no_permission_to_specify_owner(
244 244 self):
245 245 repo_group_name = 'api-repo-group'
246 246
247 247 id_, params = build_data(
248 248 self.apikey_regular, 'create_repo_group',
249 249 group_name=repo_group_name,
250 250 owner=TEST_USER_ADMIN_LOGIN,)
251 251 response = api_call(self.app, params)
252 252
253 253 expected = "Only RhodeCode super-admin can specify `owner` param"
254 254 assert_error(id_, expected, given=response.body)
255 255
256 256 @mock.patch.object(RepoGroupModel, 'create', crash)
257 257 def test_api_create_repo_group_exception_occurred(self):
258 258 repo_group_name = 'api-repo-group'
259 259
260 260 repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name)
261 261 assert repo_group is None
262 262
263 263 id_, params = build_data(
264 264 self.apikey, 'create_repo_group',
265 265 group_name=repo_group_name,
266 266 owner=TEST_USER_ADMIN_LOGIN,)
267 267 response = api_call(self.app, params)
268 268 expected = 'failed to create repo group `%s`' % (repo_group_name,)
269 269 assert_error(id_, expected, given=response.body)
270 270
271 271 def test_create_group_with_extra_slashes_in_name(self, user_util):
272 272 existing_repo_group = user_util.create_repo_group()
273 273 dirty_group_name = '//{}//group2//'.format(
274 274 existing_repo_group.group_name)
275 275 cleaned_group_name = '{}/group2'.format(
276 276 existing_repo_group.group_name)
277 277
278 278 id_, params = build_data(
279 279 self.apikey, 'create_repo_group',
280 280 group_name=dirty_group_name,
281 281 owner=TEST_USER_ADMIN_LOGIN,)
282 282 response = api_call(self.app, params)
283 283 repo_group = RepoGroupModel.cls.get_by_group_name(cleaned_group_name)
284 284 expected = {
285 285 'msg': 'Created new repo group `%s`' % (cleaned_group_name,),
286 286 'repo_group': repo_group.get_api_data()
287 287 }
288 288 assert_ok(id_, expected, given=response.body)
289 289 fixture.destroy_repo_group(cleaned_group_name)
@@ -1,192 +1,192 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.lib.auth import check_password
25 25 from rhodecode.model.user import UserModel
26 26 from rhodecode.tests import (
27 27 TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL)
28 28 from rhodecode.api.tests.utils import (
29 29 build_data, api_call, assert_ok, assert_error, jsonify, crash)
30 30 from rhodecode.tests.fixture import Fixture
31 31 from rhodecode.model.db import RepoGroup
32 32
33 33
34 34 # TODO: mikhail: remove fixture from here
35 35 fixture = Fixture()
36 36
37 37
38 38 @pytest.mark.usefixtures("testuser_api", "app")
39 39 class TestCreateUser(object):
40 40 def test_api_create_existing_user(self):
41 41 id_, params = build_data(
42 42 self.apikey, 'create_user',
43 43 username=TEST_USER_ADMIN_LOGIN,
44 44 email='test@foo.com',
45 45 password='trololo')
46 46 response = api_call(self.app, params)
47 47
48 48 expected = "user `%s` already exist" % (TEST_USER_ADMIN_LOGIN,)
49 49 assert_error(id_, expected, given=response.body)
50 50
51 51 def test_api_create_user_with_existing_email(self):
52 52 id_, params = build_data(
53 53 self.apikey, 'create_user',
54 54 username=TEST_USER_ADMIN_LOGIN + 'new',
55 55 email=TEST_USER_REGULAR_EMAIL,
56 56 password='trololo')
57 57 response = api_call(self.app, params)
58 58
59 59 expected = "email `%s` already exist" % (TEST_USER_REGULAR_EMAIL,)
60 60 assert_error(id_, expected, given=response.body)
61 61
62 62 def test_api_create_user(self):
63 63 username = 'test_new_api_user'
64 64 email = username + "@foo.com"
65 65
66 66 id_, params = build_data(
67 67 self.apikey, 'create_user',
68 68 username=username,
69 69 email=email,
70 70 password='example')
71 71 response = api_call(self.app, params)
72 72
73 73 usr = UserModel().get_by_username(username)
74 74 ret = {
75 75 'msg': 'created new user `%s`' % (username,),
76 76 'user': jsonify(usr.get_api_data(include_secrets=True)),
77 77 }
78 78 try:
79 79 expected = ret
80 80 assert check_password('example', usr.password)
81 81 assert_ok(id_, expected, given=response.body)
82 82 finally:
83 83 fixture.destroy_user(usr.user_id)
84 84
85 85 def test_api_create_user_without_password(self):
86 86 username = 'test_new_api_user_passwordless'
87 87 email = username + "@foo.com"
88 88
89 89 id_, params = build_data(
90 90 self.apikey, 'create_user',
91 91 username=username,
92 92 email=email)
93 93 response = api_call(self.app, params)
94 94
95 95 usr = UserModel().get_by_username(username)
96 96 ret = {
97 97 'msg': 'created new user `%s`' % (username,),
98 98 'user': jsonify(usr.get_api_data(include_secrets=True)),
99 99 }
100 100 try:
101 101 expected = ret
102 102 assert_ok(id_, expected, given=response.body)
103 103 finally:
104 104 fixture.destroy_user(usr.user_id)
105 105
106 106 def test_api_create_user_with_extern_name(self):
107 107 username = 'test_new_api_user_passwordless'
108 108 email = username + "@foo.com"
109 109
110 110 id_, params = build_data(
111 111 self.apikey, 'create_user',
112 112 username=username,
113 113 email=email, extern_name='rhodecode')
114 114 response = api_call(self.app, params)
115 115
116 116 usr = UserModel().get_by_username(username)
117 117 ret = {
118 118 'msg': 'created new user `%s`' % (username,),
119 119 'user': jsonify(usr.get_api_data(include_secrets=True)),
120 120 }
121 121 try:
122 122 expected = ret
123 123 assert_ok(id_, expected, given=response.body)
124 124 finally:
125 125 fixture.destroy_user(usr.user_id)
126 126
127 127 def test_api_create_user_with_password_change(self):
128 128 username = 'test_new_api_user_password_change'
129 129 email = username + "@foo.com"
130 130
131 131 id_, params = build_data(
132 132 self.apikey, 'create_user',
133 133 username=username,
134 134 email=email, extern_name='rhodecode',
135 135 force_password_change=True)
136 136 response = api_call(self.app, params)
137 137
138 138 usr = UserModel().get_by_username(username)
139 139 ret = {
140 140 'msg': 'created new user `%s`' % (username,),
141 141 'user': jsonify(usr.get_api_data(include_secrets=True)),
142 142 }
143 143 try:
144 144 expected = ret
145 145 assert_ok(id_, expected, given=response.body)
146 146 finally:
147 147 fixture.destroy_user(usr.user_id)
148 148
149 149 def test_api_create_user_with_personal_repo_group(self):
150 150 username = 'test_new_api_user_personal_group'
151 151 email = username + "@foo.com"
152 152
153 153 id_, params = build_data(
154 154 self.apikey, 'create_user',
155 155 username=username,
156 156 email=email, extern_name='rhodecode',
157 157 create_personal_repo_group=True)
158 158 response = api_call(self.app, params)
159 159
160 160 usr = UserModel().get_by_username(username)
161 161 ret = {
162 162 'msg': 'created new user `%s`' % (username,),
163 163 'user': jsonify(usr.get_api_data(include_secrets=True)),
164 164 }
165 165
166 166 personal_group = RepoGroup.get_by_group_name(username)
167 167 assert personal_group
168 168 assert personal_group.personal == True
169 169 assert personal_group.user.username == username
170 170
171 171 try:
172 172 expected = ret
173 173 assert_ok(id_, expected, given=response.body)
174 174 finally:
175 175 fixture.destroy_repo_group(username)
176 176 fixture.destroy_user(usr.user_id)
177 177
178 178
179 179 @mock.patch.object(UserModel, 'create_or_update', crash)
180 180 def test_api_create_user_when_exception_happened(self):
181 181
182 182 username = 'test_new_api_user'
183 183 email = username + "@foo.com"
184 184
185 185 id_, params = build_data(
186 186 self.apikey, 'create_user',
187 187 username=username,
188 188 email=email,
189 189 password='trololo')
190 190 response = api_call(self.app, params)
191 191 expected = 'failed to create user `%s`' % (username,)
192 192 assert_error(id_, expected, given=response.body)
@@ -1,114 +1,114 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.user import UserModel
26 26 from rhodecode.model.user_group import UserGroupModel
27 27 from rhodecode.api.tests.utils import (
28 28 build_data, api_call, assert_error, assert_ok, crash, jsonify)
29 29 from rhodecode.tests.fixture import Fixture
30 30
31 31
32 32 @pytest.mark.usefixtures("testuser_api", "app")
33 33 class TestCreateUserGroup(object):
34 34 fixture = Fixture()
35 35
36 36 def test_api_create_user_group(self):
37 37 group_name = 'some_new_group'
38 38 id_, params = build_data(
39 39 self.apikey, 'create_user_group', group_name=group_name)
40 40 response = api_call(self.app, params)
41 41
42 42 ret = {
43 43 'msg': 'created new user group `%s`' % (group_name,),
44 44 'user_group': jsonify(
45 45 UserGroupModel()
46 46 .get_by_name(group_name)
47 47 .get_api_data()
48 48 )
49 49 }
50 50 expected = ret
51 51 assert_ok(id_, expected, given=response.body)
52 52 self.fixture.destroy_user_group(group_name)
53 53
54 54 def test_api_create_user_group_regular_user(self):
55 55 group_name = 'some_new_group'
56 56
57 57 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
58 58 usr.inherit_default_permissions = False
59 59 Session().add(usr)
60 60 UserModel().grant_perm(
61 61 self.TEST_USER_LOGIN, 'hg.usergroup.create.true')
62 62 Session().commit()
63 63
64 64 id_, params = build_data(
65 65 self.apikey_regular, 'create_user_group', group_name=group_name)
66 66 response = api_call(self.app, params)
67 67
68 68 expected = {
69 69 'msg': 'created new user group `%s`' % (group_name,),
70 70 'user_group': jsonify(
71 71 UserGroupModel()
72 72 .get_by_name(group_name)
73 73 .get_api_data()
74 74 )
75 75 }
76 76 try:
77 77 assert_ok(id_, expected, given=response.body)
78 78 finally:
79 79 self.fixture.destroy_user_group(group_name)
80 80 UserModel().revoke_perm(
81 81 self.TEST_USER_LOGIN, 'hg.usergroup.create.true')
82 82 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
83 83 usr.inherit_default_permissions = True
84 84 Session().add(usr)
85 85 Session().commit()
86 86
87 87 def test_api_create_user_group_regular_user_no_permission(self):
88 88 group_name = 'some_new_group'
89 89 id_, params = build_data(
90 90 self.apikey_regular, 'create_user_group', group_name=group_name)
91 91 response = api_call(self.app, params)
92 92 expected = "Access was denied to this resource."
93 93 assert_error(id_, expected, given=response.body)
94 94
95 95 def test_api_create_user_group_that_exist(self, user_util):
96 96 group = user_util.create_user_group()
97 97 group_name = group.users_group_name
98 98
99 99 id_, params = build_data(
100 100 self.apikey, 'create_user_group', group_name=group_name)
101 101 response = api_call(self.app, params)
102 102
103 103 expected = "user group `%s` already exist" % (group_name,)
104 104 assert_error(id_, expected, given=response.body)
105 105
106 106 @mock.patch.object(UserGroupModel, 'create', crash)
107 107 def test_api_create_user_group_exception_occurred(self):
108 108 group_name = 'exception_happens'
109 109 id_, params = build_data(
110 110 self.apikey, 'create_user_group', group_name=group_name)
111 111 response = api_call(self.app, params)
112 112
113 113 expected = 'failed to create group `%s`' % (group_name,)
114 114 assert_error(id_, expected, given=response.body)
@@ -1,61 +1,61 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.gist import GistModel
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_error, assert_ok, crash)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestApiDeleteGist(object):
31 31 def test_api_delete_gist(self, gist_util):
32 32 gist_id = gist_util.create_gist().gist_access_id
33 33 id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id)
34 34 response = api_call(self.app, params)
35 35 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)}
36 36 assert_ok(id_, expected, given=response.body)
37 37
38 38 def test_api_delete_gist_regular_user(self, gist_util):
39 39 gist_id = gist_util.create_gist(
40 40 owner=self.TEST_USER_LOGIN).gist_access_id
41 41 id_, params = build_data(
42 42 self.apikey_regular, 'delete_gist', gistid=gist_id)
43 43 response = api_call(self.app, params)
44 44 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)}
45 45 assert_ok(id_, expected, given=response.body)
46 46
47 47 def test_api_delete_gist_regular_user_no_permission(self, gist_util):
48 48 gist_id = gist_util.create_gist().gist_access_id
49 49 id_, params = build_data(
50 50 self.apikey_regular, 'delete_gist', gistid=gist_id)
51 51 response = api_call(self.app, params)
52 52 expected = 'gist `%s` does not exist' % (gist_id,)
53 53 assert_error(id_, expected, given=response.body)
54 54
55 55 @mock.patch.object(GistModel, 'delete', crash)
56 56 def test_api_delete_gist_exception_occurred(self, gist_util):
57 57 gist_id = gist_util.create_gist().gist_access_id
58 58 id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id)
59 59 response = api_call(self.app, params)
60 60 expected = 'failed to delete gist ID:%s' % (gist_id,)
61 61 assert_error(id_, expected, given=response.body)
@@ -1,73 +1,73 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import mock
22 22 import pytest
23 23
24 24 from rhodecode.model.repo import RepoModel
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_error, assert_ok, crash)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestApiDeleteRepo(object):
31 31 def test_api_delete_repo(self, backend):
32 32 repo = backend.create_repo()
33 33
34 34 id_, params = build_data(
35 35 self.apikey, 'delete_repo', repoid=repo.repo_name, )
36 36 response = api_call(self.app, params)
37 37
38 38 expected = {
39 39 'msg': 'Deleted repository `%s`' % (repo.repo_name,),
40 40 'success': True
41 41 }
42 42 assert_ok(id_, expected, given=response.body)
43 43
44 44 def test_api_delete_repo_by_non_admin(self, backend, user_regular):
45 45 repo = backend.create_repo(cur_user=user_regular.username)
46 46 id_, params = build_data(
47 47 user_regular.api_key, 'delete_repo', repoid=repo.repo_name, )
48 48 response = api_call(self.app, params)
49 49
50 50 expected = {
51 51 'msg': 'Deleted repository `%s`' % (repo.repo_name,),
52 52 'success': True
53 53 }
54 54 assert_ok(id_, expected, given=response.body)
55 55
56 56 def test_api_delete_repo_by_non_admin_no_permission(
57 57 self, backend, user_regular):
58 58 repo = backend.create_repo()
59 59 id_, params = build_data(
60 60 user_regular.api_key, 'delete_repo', repoid=repo.repo_name, )
61 61 response = api_call(self.app, params)
62 62 expected = 'repository `%s` does not exist' % (repo.repo_name)
63 63 assert_error(id_, expected, given=response.body)
64 64
65 65 def test_api_delete_repo_exception_occurred(self, backend):
66 66 repo = backend.create_repo()
67 67 id_, params = build_data(
68 68 self.apikey, 'delete_repo', repoid=repo.repo_name, )
69 69 with mock.patch.object(RepoModel, 'delete', crash):
70 70 response = api_call(self.app, params)
71 71 expected = 'failed to delete repository `%s`' % (
72 72 repo.repo_name,)
73 73 assert_error(id_, expected, given=response.body)
@@ -1,86 +1,86 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.repo_group import RepoGroupModel
25 25 from rhodecode.model.user import UserModel
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_error, assert_ok)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestApiDeleteRepoGroup(object):
32 32 def test_api_delete_repo_group(self, user_util):
33 33 repo_group = user_util.create_repo_group(auto_cleanup=False)
34 34 repo_group_name = repo_group.group_name
35 35 repo_group_id = repo_group.group_id
36 36 id_, params = build_data(
37 37 self.apikey, 'delete_repo_group', repogroupid=repo_group_name, )
38 38 response = api_call(self.app, params)
39 39
40 40 ret = {
41 41 'msg': 'deleted repo group ID:%s %s' % (
42 42 repo_group_id, repo_group_name
43 43 ),
44 44 'repo_group': None
45 45 }
46 46 expected = ret
47 47 assert_ok(id_, expected, given=response.body)
48 48 gr = RepoGroupModel()._get_repo_group(repo_group_name)
49 49 assert gr is None
50 50
51 51 def test_api_delete_repo_group_regular_user(self, user_util):
52 52 repo_group = user_util.create_repo_group(auto_cleanup=False)
53 53 repo_group_name = repo_group.group_name
54 54 repo_group_id = repo_group.group_id
55 55
56 56 user = UserModel().get_by_username(self.TEST_USER_LOGIN)
57 57 user_util.grant_user_permission_to_repo_group(
58 58 repo_group, user, 'group.admin')
59 59
60 60 id_, params = build_data(
61 61 self.apikey, 'delete_repo_group', repogroupid=repo_group_name, )
62 62 response = api_call(self.app, params)
63 63
64 64 ret = {
65 65 'msg': 'deleted repo group ID:%s %s' % (
66 66 repo_group_id, repo_group_name
67 67 ),
68 68 'repo_group': None
69 69 }
70 70 expected = ret
71 71 assert_ok(id_, expected, given=response.body)
72 72 gr = RepoGroupModel()._get_repo_group(repo_group_name)
73 73 assert gr is None
74 74
75 75 def test_api_delete_repo_group_regular_user_no_permission(self, user_util):
76 76 repo_group = user_util.create_repo_group()
77 77 repo_group_name = repo_group.group_name
78 78
79 79 id_, params = build_data(
80 80 self.apikey_regular, 'delete_repo_group',
81 81 repogroupid=repo_group_name, )
82 82 response = api_call(self.app, params)
83 83
84 84 expected = 'repository group `%s` does not exist' % (
85 85 repo_group_name,)
86 86 assert_error(id_, expected, given=response.body)
@@ -1,57 +1,57 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import mock
23 23 import pytest
24 24
25 25 from rhodecode.model.user import UserModel
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_ok, assert_error, crash)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestDeleteUser(object):
32 32 def test_api_delete_user(self, user_util):
33 33 usr = user_util.create_user(auto_cleanup=False)
34 34
35 35 username = usr.username
36 36 usr_id = usr.user_id
37 37
38 38 id_, params = build_data(self.apikey, 'delete_user', userid=username)
39 39 response = api_call(self.app, params)
40 40
41 41 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
42 42 'user': None}
43 43 expected = ret
44 44 assert_ok(id_, expected, given=response.body)
45 45
46 46 @mock.patch.object(UserModel, 'delete', crash)
47 47 def test_api_delete_user_when_exception_happened(self, user_util):
48 48 usr = user_util.create_user()
49 49 username = usr.username
50 50
51 51 id_, params = build_data(
52 52 self.apikey, 'delete_user', userid=username, )
53 53 response = api_call(self.app, params)
54 54 ret = 'failed to delete user ID:%s %s' % (usr.user_id,
55 55 usr.username)
56 56 expected = ret
57 57 assert_error(id_, expected, given=response.body)
@@ -1,106 +1,106 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import mock
23 23 import pytest
24 24
25 25 from rhodecode.model.user import UserModel
26 26 from rhodecode.model.user_group import UserGroupModel
27 27 from rhodecode.api.tests.utils import (
28 28 build_data, api_call, assert_error, assert_ok, crash)
29 29
30 30
31 31 @pytest.mark.usefixtures("testuser_api", "app")
32 32 class TestDeleteUserGroup(object):
33 33 def test_api_delete_user_group(self, user_util):
34 34 user_group = user_util.create_user_group(auto_cleanup=False)
35 35 group_name = user_group.users_group_name
36 36 group_id = user_group.users_group_id
37 37 id_, params = build_data(
38 38 self.apikey, 'delete_user_group', usergroupid=group_name)
39 39 response = api_call(self.app, params)
40 40
41 41 expected = {
42 42 'user_group': None,
43 43 'msg': 'deleted user group ID:%s %s' % (group_id, group_name)
44 44 }
45 45 assert_ok(id_, expected, given=response.body)
46 46
47 47 def test_api_delete_user_group_regular_user(self, user_util):
48 48 ugroup = user_util.create_user_group(auto_cleanup=False)
49 49 group_name = ugroup.users_group_name
50 50 group_id = ugroup.users_group_id
51 51 user = UserModel().get_by_username(self.TEST_USER_LOGIN)
52 52
53 53 user_util.grant_user_permission_to_user_group(
54 54 ugroup, user, 'usergroup.admin')
55 55
56 56 id_, params = build_data(
57 57 self.apikey_regular, 'delete_user_group', usergroupid=group_name)
58 58 response = api_call(self.app, params)
59 59
60 60 expected = {
61 61 'user_group': None,
62 62 'msg': 'deleted user group ID:%s %s' % (group_id, group_name)
63 63 }
64 64 assert_ok(id_, expected, given=response.body)
65 65
66 66 def test_api_delete_user_group_regular_user_no_permission(self, user_util):
67 67 user_group = user_util.create_user_group()
68 68 group_name = user_group.users_group_name
69 69
70 70 id_, params = build_data(
71 71 self.apikey_regular, 'delete_user_group', usergroupid=group_name)
72 72 response = api_call(self.app, params)
73 73
74 74 expected = 'user group `%s` does not exist' % (group_name)
75 75 assert_error(id_, expected, given=response.body)
76 76
77 77 def test_api_delete_user_group_that_is_assigned(self, backend, user_util):
78 78 ugroup = user_util.create_user_group()
79 79 group_name = ugroup.users_group_name
80 80 repo = backend.create_repo()
81 81
82 82 ugr_to_perm = user_util.grant_user_group_permission_to_repo(
83 83 repo, ugroup, 'repository.write')
84 84 msg = 'UserGroup assigned to %s' % (ugr_to_perm.repository)
85 85
86 86 id_, params = build_data(
87 87 self.apikey, 'delete_user_group',
88 88 usergroupid=group_name)
89 89 response = api_call(self.app, params)
90 90
91 91 expected = msg
92 92 assert_error(id_, expected, given=response.body)
93 93
94 94 def test_api_delete_user_group_exception_occurred(self, user_util):
95 95 ugroup = user_util.create_user_group()
96 96 group_name = ugroup.users_group_name
97 97 group_id = ugroup.users_group_id
98 98 id_, params = build_data(
99 99 self.apikey, 'delete_user_group',
100 100 usergroupid=group_name)
101 101
102 102 with mock.patch.object(UserGroupModel, 'delete', crash):
103 103 response = api_call(self.app, params)
104 104 expected = 'failed to delete user group ID:%s %s' % (
105 105 group_id, group_name)
106 106 assert_error(id_, expected, given=response.body)
@@ -1,79 +1,79 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.api.views import deprecated_api
25 25 from rhodecode.lib.ext_json import json
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestCommitComment(object):
32 32 def test_deprecated_message_in_docstring(self):
33 33 docstring = deprecated_api.changeset_comment.__doc__
34 34 assert '.. deprecated:: 3.4.0' in docstring
35 35 assert 'Please use method `comment_commit` instead.' in docstring
36 36
37 37 def test_deprecated_message_in_retvalue(self):
38 38
39 39 id_, params = build_data(
40 40 self.apikey, 'show_ip')
41 41 response = api_call(self.app, params)
42 42
43 43 expected = {
44 44 'id': id_,
45 45 'error': None,
46 46 'result': json.loads(response.body)['result'],
47 47 'DEPRECATION_WARNING':
48 48 'DEPRECATED METHOD Please use method `get_ip` instead.'
49 49 }
50 50 assert expected == json.loads(response.body)
51 51
52 52 # def test_calls_comment_commit(self, backend, no_notifications):
53 53 # data = {
54 54 # 'repoid': backend.repo_name,
55 55 # 'status': ChangesetStatus.STATUS_APPROVED,
56 56 # 'message': 'Approved',
57 57 # 'revision': 'tip'
58 58 # }
59 59 # with patch.object(repo_api, 'changeset_commit') as comment_mock:
60 60 # id_, params = build_data(self.apikey, 'comment_commit', **data)
61 61 # api_call(self.app, params)
62 62 #
63 63 # _, call_args = comment_mock.call_args
64 64 # data['commit_id'] = data.pop('revision')
65 65 # for key in data:
66 66 # assert call_args[key] == data[key]
67 67
68 68 # def test_warning_log_contains_deprecation_message(self):
69 69 # api = self.SampleApi()
70 70 # with patch.object(utils, 'log') as log_mock:
71 71 # api.api_method()
72 72 #
73 73 # assert log_mock.warning.call_count == 1
74 74 # call_args = log_mock.warning.call_args[0]
75 75 # assert (
76 76 # call_args[0] ==
77 77 # 'DEPRECATED API CALL on function %s, please use `%s` instead')
78 78 # assert call_args[1].__name__ == 'api_method'
79 79 # assert call_args[2] == 'new_method' No newline at end of file
@@ -1,279 +1,279 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import mock
23 23 import pytest
24 24
25 25 from rhodecode.model.meta import Session
26 26 from rhodecode.model.repo import RepoModel
27 27 from rhodecode.model.repo_group import RepoGroupModel
28 28 from rhodecode.model.user import UserModel
29 29 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
30 30 from rhodecode.api.tests.utils import (
31 31 build_data, api_call, assert_error, assert_ok, crash)
32 32 from rhodecode.tests.fixture import Fixture
33 33
34 34
35 35 fixture = Fixture()
36 36
37 37
38 38 @pytest.mark.usefixtures("testuser_api", "app")
39 39 class TestApiForkRepo(object):
40 40 def test_api_fork_repo(self, backend):
41 41 source_name = backend['minimal'].repo_name
42 42 fork_name = backend.new_repo_name()
43 43
44 44 id_, params = build_data(
45 45 self.apikey, 'fork_repo',
46 46 repoid=source_name,
47 47 fork_name=fork_name,
48 48 owner=TEST_USER_ADMIN_LOGIN)
49 49 response = api_call(self.app, params)
50 50
51 51 expected = {
52 52 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name),
53 53 'success': True,
54 54 'task': None,
55 55 }
56 56 try:
57 57 assert_ok(id_, expected, given=response.body)
58 58 finally:
59 59 fixture.destroy_repo(fork_name)
60 60
61 61 def test_api_fork_repo_into_group(self, backend, user_util):
62 62 source_name = backend['minimal'].repo_name
63 63 repo_group = user_util.create_repo_group()
64 64 fork_name = '%s/api-repo-fork' % repo_group.group_name
65 65 id_, params = build_data(
66 66 self.apikey, 'fork_repo',
67 67 repoid=source_name,
68 68 fork_name=fork_name,
69 69 owner=TEST_USER_ADMIN_LOGIN)
70 70 response = api_call(self.app, params)
71 71
72 72 ret = {
73 73 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name),
74 74 'success': True,
75 75 'task': None,
76 76 }
77 77 expected = ret
78 78 try:
79 79 assert_ok(id_, expected, given=response.body)
80 80 finally:
81 81 fixture.destroy_repo(fork_name)
82 82
83 83 def test_api_fork_repo_non_admin(self, backend):
84 84 source_name = backend['minimal'].repo_name
85 85 fork_name = backend.new_repo_name()
86 86
87 87 id_, params = build_data(
88 88 self.apikey_regular, 'fork_repo',
89 89 repoid=source_name,
90 90 fork_name=fork_name)
91 91 response = api_call(self.app, params)
92 92
93 93 expected = {
94 94 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name),
95 95 'success': True,
96 96 'task': None,
97 97 }
98 98 try:
99 99 assert_ok(id_, expected, given=response.body)
100 100 finally:
101 101 fixture.destroy_repo(fork_name)
102 102
103 103 def test_api_fork_repo_non_admin_into_group_no_permission(self, backend, user_util):
104 104 source_name = backend['minimal'].repo_name
105 105 repo_group = user_util.create_repo_group()
106 106 repo_group_name = repo_group.group_name
107 107 fork_name = '%s/api-repo-fork' % repo_group_name
108 108
109 109 id_, params = build_data(
110 110 self.apikey_regular, 'fork_repo',
111 111 repoid=source_name,
112 112 fork_name=fork_name)
113 113 response = api_call(self.app, params)
114 114
115 115 expected = {
116 116 'repo_group': 'Repository group `{}` does not exist'.format(
117 117 repo_group_name)}
118 118 try:
119 119 assert_error(id_, expected, given=response.body)
120 120 finally:
121 121 fixture.destroy_repo(fork_name)
122 122
123 123 def test_api_fork_repo_non_admin_into_group(self, backend, user_util):
124 124 source_name = backend['minimal'].repo_name
125 125 repo_group = user_util.create_repo_group()
126 126 fork_name = '%s/api-repo-fork' % repo_group.group_name
127 127
128 128 RepoGroupModel().grant_user_permission(
129 129 repo_group, self.TEST_USER_LOGIN, 'group.admin')
130 130 Session().commit()
131 131
132 132 id_, params = build_data(
133 133 self.apikey_regular, 'fork_repo',
134 134 repoid=source_name,
135 135 fork_name=fork_name)
136 136 response = api_call(self.app, params)
137 137
138 138 expected = {
139 139 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name),
140 140 'success': True,
141 141 'task': None,
142 142 }
143 143 try:
144 144 assert_ok(id_, expected, given=response.body)
145 145 finally:
146 146 fixture.destroy_repo(fork_name)
147 147
148 148 def test_api_fork_repo_non_admin_specify_owner(self, backend):
149 149 source_name = backend['minimal'].repo_name
150 150 fork_name = backend.new_repo_name()
151 151 id_, params = build_data(
152 152 self.apikey_regular, 'fork_repo',
153 153 repoid=source_name,
154 154 fork_name=fork_name,
155 155 owner=TEST_USER_ADMIN_LOGIN)
156 156 response = api_call(self.app, params)
157 157 expected = 'Only RhodeCode super-admin can specify `owner` param'
158 158 assert_error(id_, expected, given=response.body)
159 159
160 160 def test_api_fork_repo_non_admin_no_permission_of_source_repo(
161 161 self, backend):
162 162 source_name = backend['minimal'].repo_name
163 163 RepoModel().grant_user_permission(repo=source_name,
164 164 user=self.TEST_USER_LOGIN,
165 165 perm='repository.none')
166 166 fork_name = backend.new_repo_name()
167 167 id_, params = build_data(
168 168 self.apikey_regular, 'fork_repo',
169 169 repoid=backend.repo_name,
170 170 fork_name=fork_name)
171 171 response = api_call(self.app, params)
172 172 expected = 'repository `%s` does not exist' % (backend.repo_name)
173 173 assert_error(id_, expected, given=response.body)
174 174
175 175 def test_api_fork_repo_non_admin_no_permission_to_fork_to_root_level(
176 176 self, backend, user_util):
177 177
178 178 regular_user = user_util.create_user()
179 179 regular_user_api_key = regular_user.api_key
180 180 usr = UserModel().get_by_username(regular_user.username)
181 181 usr.inherit_default_permissions = False
182 182 Session().add(usr)
183 183 UserModel().grant_perm(regular_user.username, 'hg.fork.repository')
184 184
185 185 source_name = backend['minimal'].repo_name
186 186 fork_name = backend.new_repo_name()
187 187 id_, params = build_data(
188 188 regular_user_api_key, 'fork_repo',
189 189 repoid=source_name,
190 190 fork_name=fork_name)
191 191 response = api_call(self.app, params)
192 192 expected = {
193 193 "repo_name": "You do not have the permission to "
194 194 "store repositories in the root location."}
195 195 assert_error(id_, expected, given=response.body)
196 196
197 197 def test_api_fork_repo_non_admin_no_permission_to_fork(
198 198 self, backend, user_util):
199 199
200 200 regular_user = user_util.create_user()
201 201 regular_user_api_key = regular_user.api_key
202 202 usr = UserModel().get_by_username(regular_user.username)
203 203 usr.inherit_default_permissions = False
204 204 Session().add(usr)
205 205
206 206 source_name = backend['minimal'].repo_name
207 207 fork_name = backend.new_repo_name()
208 208 id_, params = build_data(
209 209 regular_user_api_key, 'fork_repo',
210 210 repoid=source_name,
211 211 fork_name=fork_name)
212 212 response = api_call(self.app, params)
213 213
214 214 expected = "Access was denied to this resource."
215 215 assert_error(id_, expected, given=response.body)
216 216
217 217 def test_api_fork_repo_unknown_owner(self, backend):
218 218 source_name = backend['minimal'].repo_name
219 219 fork_name = backend.new_repo_name()
220 220 owner = 'i-dont-exist'
221 221 id_, params = build_data(
222 222 self.apikey, 'fork_repo',
223 223 repoid=source_name,
224 224 fork_name=fork_name,
225 225 owner=owner)
226 226 response = api_call(self.app, params)
227 227 expected = 'user `%s` does not exist' % (owner,)
228 228 assert_error(id_, expected, given=response.body)
229 229
230 230 def test_api_fork_repo_fork_exists(self, backend):
231 231 source_name = backend['minimal'].repo_name
232 232 fork_name = backend.new_repo_name()
233 233 fork_repo = fixture.create_fork(source_name, fork_name)
234 234
235 235 id_, params = build_data(
236 236 self.apikey, 'fork_repo',
237 237 repoid=source_name,
238 238 fork_name=fork_name,
239 239 owner=TEST_USER_ADMIN_LOGIN)
240 240 response = api_call(self.app, params)
241 241
242 242 try:
243 243 expected = {
244 244 'unique_repo_name': 'Repository with name `{}` already exists'.format(
245 245 fork_name)}
246 246 assert_error(id_, expected, given=response.body)
247 247 finally:
248 248 fixture.destroy_repo(fork_repo.repo_name)
249 249
250 250 def test_api_fork_repo_repo_exists(self, backend):
251 251 source_name = backend['minimal'].repo_name
252 252 fork_name = source_name
253 253
254 254 id_, params = build_data(
255 255 self.apikey, 'fork_repo',
256 256 repoid=source_name,
257 257 fork_name=fork_name,
258 258 owner=TEST_USER_ADMIN_LOGIN)
259 259 response = api_call(self.app, params)
260 260
261 261 expected = {
262 262 'unique_repo_name': 'Repository with name `{}` already exists'.format(
263 263 fork_name)}
264 264 assert_error(id_, expected, given=response.body)
265 265
266 266 @mock.patch.object(RepoModel, 'create_fork', crash)
267 267 def test_api_fork_repo_exception_occurred(self, backend):
268 268 source_name = backend['minimal'].repo_name
269 269 fork_name = backend.new_repo_name()
270 270 id_, params = build_data(
271 271 self.apikey, 'fork_repo',
272 272 repoid=source_name,
273 273 fork_name=fork_name,
274 274 owner=TEST_USER_ADMIN_LOGIN)
275 275 response = api_call(self.app, params)
276 276
277 277 expected = 'failed to fork repository `%s` as `%s`' % (source_name,
278 278 fork_name)
279 279 assert_error(id_, expected, given=response.body)
@@ -1,101 +1,101 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.db import Gist
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_error, assert_ok)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestApiGetGist(object):
31 31 def test_api_get_gist(self, gist_util):
32 32 gist = gist_util.create_gist()
33 33 gist_id = gist.gist_access_id
34 34 gist_created_on = gist.created_on
35 35 gist_modified_at = gist.modified_at
36 36 id_, params = build_data(
37 37 self.apikey, 'get_gist', gistid=gist_id, )
38 38 response = api_call(self.app, params)
39 39
40 40 expected = {
41 41 'access_id': gist_id,
42 42 'created_on': gist_created_on,
43 43 'modified_at': gist_modified_at,
44 44 'description': 'new-gist',
45 45 'expires': -1.0,
46 46 'gist_id': int(gist_id),
47 47 'type': 'public',
48 48 'url': 'http://test.example.com:80/_admin/gists/%s' % (gist_id,),
49 49 'acl_level': Gist.ACL_LEVEL_PUBLIC,
50 50 'content': None,
51 51 }
52 52
53 53 assert_ok(id_, expected, given=response.body)
54 54
55 55 def test_api_get_gist_with_content(self, gist_util):
56 56 mapping = {
57 57 u'filename1.txt': {'content': u'hello world'},
58 58 u'filename1ą.txt': {'content': u'hello worldę'}
59 59 }
60 60 gist = gist_util.create_gist(gist_mapping=mapping)
61 61 gist_id = gist.gist_access_id
62 62 gist_created_on = gist.created_on
63 63 gist_modified_at = gist.modified_at
64 64 id_, params = build_data(
65 65 self.apikey, 'get_gist', gistid=gist_id, content=True)
66 66 response = api_call(self.app, params)
67 67
68 68 expected = {
69 69 'access_id': gist_id,
70 70 'created_on': gist_created_on,
71 71 'modified_at': gist_modified_at,
72 72 'description': 'new-gist',
73 73 'expires': -1.0,
74 74 'gist_id': int(gist_id),
75 75 'type': 'public',
76 76 'url': 'http://test.example.com:80/_admin/gists/%s' % (gist_id,),
77 77 'acl_level': Gist.ACL_LEVEL_PUBLIC,
78 78 'content': {
79 79 u'filename1.txt': u'hello world',
80 80 u'filename1ą.txt': u'hello worldę'
81 81 },
82 82 }
83 83
84 84 assert_ok(id_, expected, given=response.body)
85 85
86 86 def test_api_get_gist_not_existing(self):
87 87 id_, params = build_data(
88 88 self.apikey_regular, 'get_gist', gistid='12345', )
89 89 response = api_call(self.app, params)
90 90 expected = 'gist `%s` does not exist' % ('12345',)
91 91 assert_error(id_, expected, given=response.body)
92 92
93 93 def test_api_get_gist_private_gist_without_permission(self, gist_util):
94 94 gist = gist_util.create_gist()
95 95 gist_id = gist.gist_access_id
96 96 id_, params = build_data(
97 97 self.apikey_regular, 'get_gist', gistid=gist_id, )
98 98 response = api_call(self.app, params)
99 99
100 100 expected = 'gist `%s` does not exist' % (gist_id,)
101 101 assert_error(id_, expected, given=response.body)
@@ -1,74 +1,74 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_error)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestApiGetGist(object):
31 31 def test_api_get_gists(self, gist_util):
32 32 gist_util.create_gist()
33 33 gist_util.create_gist()
34 34
35 35 id_, params = build_data(self.apikey, 'get_gists')
36 36 response = api_call(self.app, params)
37 37 assert len(response.json['result']) == 2
38 38
39 39 def test_api_get_gists_regular_user(self, gist_util):
40 40 # by admin
41 41 gist_util.create_gist()
42 42 gist_util.create_gist()
43 43
44 44 # by reg user
45 45 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
46 46 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
47 47 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
48 48
49 49 id_, params = build_data(self.apikey_regular, 'get_gists')
50 50 response = api_call(self.app, params)
51 51 assert len(response.json['result']) == 3
52 52
53 53 def test_api_get_gists_only_for_regular_user(self, gist_util):
54 54 # by admin
55 55 gist_util.create_gist()
56 56 gist_util.create_gist()
57 57
58 58 # by reg user
59 59 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
60 60 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
61 61 gist_util.create_gist(owner=self.TEST_USER_LOGIN)
62 62
63 63 id_, params = build_data(
64 64 self.apikey, 'get_gists', userid=self.TEST_USER_LOGIN)
65 65 response = api_call(self.app, params)
66 66 assert len(response.json['result']) == 3
67 67
68 68 def test_api_get_gists_regular_user_with_different_userid(self):
69 69 id_, params = build_data(
70 70 self.apikey_regular, 'get_gists',
71 71 userid=TEST_USER_ADMIN_LOGIN)
72 72 response = api_call(self.app, params)
73 73 expected = 'userid is not the same as your user'
74 74 assert_error(id_, expected, given=response.body)
@@ -1,36 +1,36 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.api.tests.utils import build_data, api_call, assert_ok
25 25
26 26
27 27 @pytest.mark.usefixtures("testuser_api", "app")
28 28 class TestGetIp(object):
29 29 def test_api_get_ip(self):
30 30 id_, params = build_data(self.apikey, 'get_ip')
31 31 response = api_call(self.app, params)
32 32 expected = {
33 33 'server_ip_addr': '0.0.0.0',
34 34 'user_ips': []
35 35 }
36 36 assert_ok(id_, expected, given=response.body)
@@ -1,91 +1,91 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.db import Repository, User
25 25 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_ok, assert_error)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestGetLocks(object):
32 32 def test_api_get_user_locks_regular_user(self):
33 33 id_, params = build_data(self.apikey_regular, 'get_user_locks')
34 34 response = api_call(self.app, params)
35 35 expected = []
36 36 assert_ok(id_, expected, given=response.body)
37 37
38 38 def test_api_get_user_locks_with_userid_regular_user(self):
39 39 id_, params = build_data(
40 40 self.apikey_regular, 'get_user_locks', userid=TEST_USER_ADMIN_LOGIN)
41 41 response = api_call(self.app, params)
42 42 expected = 'userid is not the same as your user'
43 43 assert_error(id_, expected, given=response.body)
44 44
45 45 def test_api_get_user_locks(self):
46 46 id_, params = build_data(self.apikey, 'get_user_locks')
47 47 response = api_call(self.app, params)
48 48 expected = []
49 49 assert_ok(id_, expected, given=response.body)
50 50
51 51 @pytest.mark.parametrize("apikey_attr, expect_secrets", [
52 52 ('apikey', True),
53 53 ('apikey_regular', False),
54 54 ])
55 55 def test_api_get_user_locks_with_one_locked_repo(
56 56 self, apikey_attr, expect_secrets, backend):
57 57
58 58 repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN)
59 59 Repository.lock(
60 60 repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
61 61
62 62 apikey = getattr(self, apikey_attr)
63 63
64 64 id_, params = build_data(apikey, 'get_user_locks')
65 65 if apikey_attr == 'apikey':
66 66 # super-admin should call in specific user
67 67 id_, params = build_data(apikey, 'get_user_locks',
68 68 userid=self.TEST_USER_LOGIN)
69 69
70 70 response = api_call(self.app, params)
71 71 expected = [repo.get_api_data(include_secrets=expect_secrets)]
72 72 assert_ok(id_, expected, given=response.body)
73 73
74 74 def test_api_get_user_locks_with_one_locked_repo_for_specific_user(
75 75 self, backend):
76 76 repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN)
77 77
78 78 Repository.lock(repo, User.get_by_username(
79 79 self.TEST_USER_LOGIN).user_id)
80 80 id_, params = build_data(
81 81 self.apikey, 'get_user_locks', userid=self.TEST_USER_LOGIN)
82 82 response = api_call(self.app, params)
83 83 expected = [repo.get_api_data(include_secrets=True)]
84 84 assert_ok(id_, expected, given=response.body)
85 85
86 86 def test_api_get_user_locks_with_userid(self):
87 87 id_, params = build_data(
88 88 self.apikey, 'get_user_locks', userid=TEST_USER_REGULAR_LOGIN)
89 89 response = api_call(self.app, params)
90 90 expected = []
91 91 assert_ok(id_, expected, given=response.body)
@@ -1,133 +1,133 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import mock
23 23 import pytest
24 24 import urlobject
25 25 from pylons import url
26 26
27 27 from rhodecode.api.tests.utils import (
28 28 build_data, api_call, assert_error, assert_ok)
29 29
30 30 pytestmark = pytest.mark.backends("git", "hg")
31 31
32 32
33 33 @pytest.mark.usefixtures("testuser_api", "app")
34 34 class TestGetPullRequest(object):
35 35
36 36 def test_api_get_pull_request(self, pr_util):
37 37 from rhodecode.model.pull_request import PullRequestModel
38 38 pull_request = pr_util.create_pull_request(mergeable=True)
39 39 id_, params = build_data(
40 40 self.apikey, 'get_pull_request',
41 41 repoid=pull_request.target_repo.repo_name,
42 42 pullrequestid=pull_request.pull_request_id)
43 43
44 44 response = api_call(self.app, params)
45 45
46 46 assert response.status == '200 OK'
47 47
48 48 url_obj = urlobject.URLObject(
49 49 url(
50 50 'pullrequest_show',
51 51 repo_name=pull_request.target_repo.repo_name,
52 52 pull_request_id=pull_request.pull_request_id, qualified=True))
53 53 pr_url = unicode(
54 54 url_obj.with_netloc('test.example.com:80'))
55 55 source_url = unicode(
56 56 pull_request.source_repo.clone_url()
57 57 .with_netloc('test.example.com:80'))
58 58 target_url = unicode(
59 59 pull_request.target_repo.clone_url()
60 60 .with_netloc('test.example.com:80'))
61 61 shadow_url = unicode(
62 62 PullRequestModel().get_shadow_clone_url(pull_request))
63 63 expected = {
64 64 'pull_request_id': pull_request.pull_request_id,
65 65 'url': pr_url,
66 66 'title': pull_request.title,
67 67 'description': pull_request.description,
68 68 'status': pull_request.status,
69 69 'created_on': pull_request.created_on,
70 70 'updated_on': pull_request.updated_on,
71 71 'commit_ids': pull_request.revisions,
72 72 'review_status': pull_request.calculated_review_status(),
73 73 'mergeable': {
74 74 'status': True,
75 75 'message': 'This pull request can be automatically merged.',
76 76 },
77 77 'source': {
78 78 'clone_url': source_url,
79 79 'repository': pull_request.source_repo.repo_name,
80 80 'reference': {
81 81 'name': pull_request.source_ref_parts.name,
82 82 'type': pull_request.source_ref_parts.type,
83 83 'commit_id': pull_request.source_ref_parts.commit_id,
84 84 },
85 85 },
86 86 'target': {
87 87 'clone_url': target_url,
88 88 'repository': pull_request.target_repo.repo_name,
89 89 'reference': {
90 90 'name': pull_request.target_ref_parts.name,
91 91 'type': pull_request.target_ref_parts.type,
92 92 'commit_id': pull_request.target_ref_parts.commit_id,
93 93 },
94 94 },
95 95 'merge': {
96 96 'clone_url': shadow_url,
97 97 'reference': {
98 98 'name': pull_request.shadow_merge_ref.name,
99 99 'type': pull_request.shadow_merge_ref.type,
100 100 'commit_id': pull_request.shadow_merge_ref.commit_id,
101 101 },
102 102 },
103 103 'author': pull_request.author.get_api_data(include_secrets=False,
104 104 details='basic'),
105 105 'reviewers': [
106 106 {
107 107 'user': reviewer.get_api_data(include_secrets=False,
108 108 details='basic'),
109 109 'reasons': reasons,
110 110 'review_status': st[0][1].status if st else 'not_reviewed',
111 111 }
112 112 for reviewer, reasons, st in pull_request.reviewers_statuses()
113 113 ]
114 114 }
115 115 assert_ok(id_, expected, response.body)
116 116
117 117 def test_api_get_pull_request_repo_error(self):
118 118 id_, params = build_data(
119 119 self.apikey, 'get_pull_request',
120 120 repoid=666, pullrequestid=1)
121 121 response = api_call(self.app, params)
122 122
123 123 expected = 'repository `666` does not exist'
124 124 assert_error(id_, expected, given=response.body)
125 125
126 126 def test_api_get_pull_request_pull_request_error(self):
127 127 id_, params = build_data(
128 128 self.apikey, 'get_pull_request',
129 129 repoid=1, pullrequestid=666)
130 130 response = api_call(self.app, params)
131 131
132 132 expected = 'pull request `666` does not exist'
133 133 assert_error(id_, expected, given=response.body)
@@ -1,80 +1,80 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.pull_request import PullRequestModel
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_error)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestGetPullRequest(object):
32 32 @pytest.mark.backends("git", "hg")
33 33 def test_api_get_pull_requests(self, pr_util):
34 34 pull_request = pr_util.create_pull_request()
35 35 pull_request_2 = PullRequestModel().create(
36 36 created_by=pull_request.author,
37 37 source_repo=pull_request.source_repo,
38 38 source_ref=pull_request.source_ref,
39 39 target_repo=pull_request.target_repo,
40 40 target_ref=pull_request.target_ref,
41 41 revisions=pull_request.revisions,
42 42 reviewers=(),
43 43 title=pull_request.title,
44 44 description=pull_request.description,
45 45 )
46 46 Session().commit()
47 47 id_, params = build_data(
48 48 self.apikey, 'get_pull_requests',
49 49 repoid=pull_request.target_repo.repo_name)
50 50 response = api_call(self.app, params)
51 51 assert response.status == '200 OK'
52 52 assert len(response.json['result']) == 2
53 53
54 54 PullRequestModel().close_pull_request(
55 55 pull_request_2, pull_request_2.author)
56 56 Session().commit()
57 57
58 58 id_, params = build_data(
59 59 self.apikey, 'get_pull_requests',
60 60 repoid=pull_request.target_repo.repo_name,
61 61 status='new')
62 62 response = api_call(self.app, params)
63 63 assert response.status == '200 OK'
64 64 assert len(response.json['result']) == 1
65 65
66 66 id_, params = build_data(
67 67 self.apikey, 'get_pull_requests',
68 68 repoid=pull_request.target_repo.repo_name,
69 69 status='closed')
70 70 response = api_call(self.app, params)
71 71 assert response.status == '200 OK'
72 72 assert len(response.json['result']) == 1
73 73
74 74 @pytest.mark.backends("git", "hg")
75 75 def test_api_get_pull_requests_repo_error(self):
76 76 id_, params = build_data(self.apikey, 'get_pull_requests', repoid=666)
77 77 response = api_call(self.app, params)
78 78
79 79 expected = 'repository `666` does not exist'
80 80 assert_error(id_, expected, given=response.body)
@@ -1,139 +1,139 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.repo import RepoModel
26 26 from rhodecode.model.user import UserModel
27 27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
28 28 from rhodecode.api.tests.utils import (
29 29 build_data, api_call, assert_ok, assert_error, expected_permissions)
30 30
31 31
32 32 @pytest.mark.usefixtures("testuser_api", "app")
33 33 class TestGetRepo(object):
34 34 @pytest.mark.parametrize("apikey_attr, expect_secrets", [
35 35 ('apikey', True),
36 36 ('apikey_regular', False),
37 37 ])
38 38 @pytest.mark.parametrize("cache_param", [
39 39 True,
40 40 False,
41 41 None,
42 42 ])
43 43 def test_api_get_repo(
44 44 self, apikey_attr, expect_secrets, cache_param, backend,
45 45 user_util):
46 46 repo = backend.create_repo()
47 47 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
48 48 group = user_util.create_user_group(members=[usr])
49 49 user_util.grant_user_group_permission_to_repo(
50 50 repo=repo, user_group=group, permission_name='repository.read')
51 51 Session().commit()
52 52 kwargs = {
53 53 'repoid': repo.repo_name,
54 54 }
55 55 if cache_param is not None:
56 56 kwargs['cache'] = cache_param
57 57
58 58 apikey = getattr(self, apikey_attr)
59 59 id_, params = build_data(apikey, 'get_repo', **kwargs)
60 60 response = api_call(self.app, params)
61 61
62 62 ret = repo.get_api_data()
63 63
64 64 permissions = expected_permissions(repo)
65 65
66 66 followers = []
67 67 for user in repo.followers:
68 68 followers.append(user.user.get_api_data(
69 69 include_secrets=expect_secrets))
70 70
71 71 ret['members'] = permissions
72 72 ret['permissions'] = permissions
73 73 ret['followers'] = followers
74 74
75 75 expected = ret
76 76
77 77 assert_ok(id_, expected, given=response.body)
78 78
79 79 @pytest.mark.parametrize("grant_perm", [
80 80 'repository.admin',
81 81 'repository.write',
82 82 'repository.read',
83 83 ])
84 84 def test_api_get_repo_by_non_admin(self, grant_perm, backend):
85 85 # TODO: Depending on which tests are running before this one, we
86 86 # start with a different number of permissions in the database.
87 87 repo = RepoModel().get_by_repo_name(backend.repo_name)
88 88 permission_count = len(repo.repo_to_perm)
89 89
90 90 RepoModel().grant_user_permission(repo=backend.repo_name,
91 91 user=self.TEST_USER_LOGIN,
92 92 perm=grant_perm)
93 93 Session().commit()
94 94 id_, params = build_data(
95 95 self.apikey_regular, 'get_repo', repoid=backend.repo_name)
96 96 response = api_call(self.app, params)
97 97
98 98 repo = RepoModel().get_by_repo_name(backend.repo_name)
99 99 ret = repo.get_api_data()
100 100
101 101 assert permission_count + 1, len(repo.repo_to_perm)
102 102
103 103 permissions = expected_permissions(repo)
104 104
105 105 followers = []
106 106 for user in repo.followers:
107 107 followers.append(user.user.get_api_data())
108 108
109 109 ret['members'] = permissions
110 110 ret['permissions'] = permissions
111 111 ret['followers'] = followers
112 112
113 113 expected = ret
114 114 try:
115 115 assert_ok(id_, expected, given=response.body)
116 116 finally:
117 117 RepoModel().revoke_user_permission(
118 118 backend.repo_name, self.TEST_USER_LOGIN)
119 119
120 120 def test_api_get_repo_by_non_admin_no_permission_to_repo(self, backend):
121 121 RepoModel().grant_user_permission(repo=backend.repo_name,
122 122 user=self.TEST_USER_LOGIN,
123 123 perm='repository.none')
124 124
125 125 id_, params = build_data(
126 126 self.apikey_regular, 'get_repo', repoid=backend.repo_name)
127 127 response = api_call(self.app, params)
128 128
129 129 expected = 'repository `%s` does not exist' % (backend.repo_name)
130 130 assert_error(id_, expected, given=response.body)
131 131
132 132 def test_api_get_repo_not_existing(self):
133 133 id_, params = build_data(
134 134 self.apikey, 'get_repo', repoid='no-such-repo')
135 135 response = api_call(self.app, params)
136 136
137 137 ret = 'repository `%s` does not exist' % 'no-such-repo'
138 138 expected = ret
139 139 assert_error(id_, expected, given=response.body)
@@ -1,140 +1,140 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.api.tests.utils import build_data, api_call, assert_error
25 25
26 26
27 27 @pytest.mark.usefixtures("testuser_api", "app")
28 28 class TestGetRepoChangeset(object):
29 29 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
30 30 def test_get_repo_changeset(self, details, backend):
31 31 commit = backend.repo.get_commit(commit_idx=0)
32 32 __, params = build_data(
33 33 self.apikey, 'get_repo_changeset',
34 34 repoid=backend.repo_name, revision=commit.raw_id,
35 35 details=details,
36 36 )
37 37 response = api_call(self.app, params)
38 38 result = response.json['result']
39 39 assert result['revision'] == 0
40 40 assert result['raw_id'] == commit.raw_id
41 41
42 42 if details == 'full':
43 43 assert result['refs']['bookmarks'] == getattr(
44 44 commit, 'bookmarks', [])
45 45 assert result['refs']['branches'] == [commit.branch]
46 46 assert result['refs']['tags'] == commit.tags
47 47
48 48 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
49 49 def test_get_repo_changeset_bad_type(self, details, backend):
50 50 id_, params = build_data(
51 51 self.apikey, 'get_repo_changeset',
52 52 repoid=backend.repo_name, revision=0,
53 53 details=details,
54 54 )
55 55 response = api_call(self.app, params)
56 56 expected = 'commit_id must be a string value'
57 57 assert_error(id_, expected, given=response.body)
58 58
59 59 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
60 60 def test_get_repo_changesets(self, details, backend):
61 61 limit = 2
62 62 commit = backend.repo.get_commit(commit_idx=0)
63 63 __, params = build_data(
64 64 self.apikey, 'get_repo_changesets',
65 65 repoid=backend.repo_name, start_rev=commit.raw_id, limit=limit,
66 66 details=details,
67 67 )
68 68 response = api_call(self.app, params)
69 69 result = response.json['result']
70 70 assert result
71 71 assert len(result) == limit
72 72 for x in xrange(limit):
73 73 assert result[x]['revision'] == x
74 74
75 75 if details == 'full':
76 76 for x in xrange(limit):
77 77 assert 'bookmarks' in result[x]['refs']
78 78 assert 'branches' in result[x]['refs']
79 79 assert 'tags' in result[x]['refs']
80 80
81 81 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
82 82 @pytest.mark.parametrize("start_rev, expected_revision", [
83 83 ("0", 0),
84 84 ("10", 10),
85 85 ("20", 20),
86 86 ])
87 87 @pytest.mark.backends("hg", "git")
88 88 def test_get_repo_changesets_commit_range(
89 89 self, details, backend, start_rev, expected_revision):
90 90 limit = 10
91 91 __, params = build_data(
92 92 self.apikey, 'get_repo_changesets',
93 93 repoid=backend.repo_name, start_rev=start_rev, limit=limit,
94 94 details=details,
95 95 )
96 96 response = api_call(self.app, params)
97 97 result = response.json['result']
98 98 assert result
99 99 assert len(result) == limit
100 100 for i in xrange(limit):
101 101 assert result[i]['revision'] == int(expected_revision) + i
102 102
103 103 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
104 104 @pytest.mark.parametrize("start_rev, expected_revision", [
105 105 ("0", 0),
106 106 ("10", 9),
107 107 ("20", 19),
108 108 ])
109 109 def test_get_repo_changesets_commit_range_svn(
110 110 self, details, backend_svn, start_rev, expected_revision):
111 111
112 112 # TODO: johbo: SVN showed a problem here: The parameter "start_rev"
113 113 # in our API allows to pass in a "Commit ID" as well as a
114 114 # "Commit Index". In the case of Subversion it is not possible to
115 115 # distinguish these cases. As a workaround we implemented this
116 116 # behavior which gives a preference to see it as a "Commit ID".
117 117
118 118 limit = 10
119 119 __, params = build_data(
120 120 self.apikey, 'get_repo_changesets',
121 121 repoid=backend_svn.repo_name, start_rev=start_rev, limit=limit,
122 122 details=details,
123 123 )
124 124 response = api_call(self.app, params)
125 125 result = response.json['result']
126 126 assert result
127 127 assert len(result) == limit
128 128 for i in xrange(limit):
129 129 assert result[i]['revision'] == int(expected_revision) + i
130 130
131 131 @pytest.mark.parametrize("details", ['basic', 'extended', 'full'])
132 132 def test_get_repo_changesets_bad_type(self, details, backend):
133 133 id_, params = build_data(
134 134 self.apikey, 'get_repo_changesets',
135 135 repoid=backend.repo_name, start_rev=0, limit=2,
136 136 details=details,
137 137 )
138 138 response = api_call(self.app, params)
139 139 expected = 'commit_id must be a string value'
140 140 assert_error(id_, expected, given=response.body)
@@ -1,55 +1,55 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.repo_group import RepoGroupModel
25 25 from rhodecode.api.tests.utils import (
26 26 build_data, api_call, assert_ok, assert_error, expected_permissions)
27 27
28 28
29 29 @pytest.mark.usefixtures("testuser_api", "app")
30 30 class TestApiGetRepoGroup(object):
31 31 def test_api_get_repo_group(self, user_util):
32 32 repo_group = user_util.create_repo_group()
33 33 repo_group_name = repo_group.group_name
34 34
35 35 id_, params = build_data(
36 36 self.apikey, 'get_repo_group', repogroupid=repo_group_name)
37 37 response = api_call(self.app, params)
38 38
39 39 repo_group = RepoGroupModel()._get_repo_group(repo_group_name)
40 40 ret = repo_group.get_api_data()
41 41
42 42 permissions = expected_permissions(repo_group)
43 43
44 44 ret['members'] = permissions
45 45 expected = ret
46 46 assert_ok(id_, expected, given=response.body)
47 47
48 48 def test_api_get_repo_group_not_existing(self):
49 49 id_, params = build_data(
50 50 self.apikey, 'get_repo_group', repogroupid='no-such-repo-group')
51 51 response = api_call(self.app, params)
52 52
53 53 ret = 'repository group `%s` does not exist' % 'no-such-repo-group'
54 54 expected = ret
55 55 assert_error(id_, expected, given=response.body)
@@ -1,40 +1,40 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.repo_group import RepoGroupModel
25 25 from rhodecode.api.tests.utils import build_data, api_call, assert_ok, jsonify
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestApiGetRepoGroups(object):
30 30 def test_api_get_repo_groups(self):
31 31 id_, params = build_data(self.apikey, 'get_repo_groups')
32 32 response = api_call(self.app, params)
33 33
34 34 result = []
35 35 for repo in RepoGroupModel().get_all():
36 36 result.append(repo.get_api_data())
37 37 ret = jsonify(result)
38 38
39 39 expected = ret
40 40 assert_ok(id_, expected, given=response.body)
@@ -1,142 +1,142 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.repo import RepoModel
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_error, assert_ok)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestGetRepoNodes(object):
32 32 @pytest.mark.parametrize("name, ret_type", [
33 33 ('all', 'all'),
34 34 ('dirs', 'dirs'),
35 35 ('files', 'files'),
36 36 ])
37 37 def test_api_get_repo_nodes(self, name, ret_type, backend):
38 38 commit_id = 'tip'
39 39 path = '/'
40 40 id_, params = build_data(
41 41 self.apikey, 'get_repo_nodes',
42 42 repoid=backend.repo_name, revision=commit_id,
43 43 root_path=path,
44 44 ret_type=ret_type)
45 45 response = api_call(self.app, params)
46 46
47 47 # we don't the actual return types here since it's tested somewhere
48 48 # else
49 49 expected = response.json['result']
50 50 assert_ok(id_, expected, given=response.body)
51 51
52 52 def test_api_get_repo_nodes_bad_commits(self, backend):
53 53 commit_id = 'i-dont-exist'
54 54 path = '/'
55 55 id_, params = build_data(
56 56 self.apikey, 'get_repo_nodes',
57 57 repoid=backend.repo_name, revision=commit_id,
58 58 root_path=path, )
59 59 response = api_call(self.app, params)
60 60
61 61 expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,)
62 62 assert_error(id_, expected, given=response.body)
63 63
64 64 def test_api_get_repo_nodes_bad_path(self, backend):
65 65 commit_id = 'tip'
66 66 path = '/idontexits'
67 67 id_, params = build_data(
68 68 self.apikey, 'get_repo_nodes',
69 69 repoid=backend.repo_name, revision=commit_id,
70 70 root_path=path, )
71 71 response = api_call(self.app, params)
72 72
73 73 expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,)
74 74 assert_error(id_, expected, given=response.body)
75 75
76 76 def test_api_get_repo_nodes_max_file_bytes(self, backend):
77 77 commit_id = 'tip'
78 78 path = '/'
79 79 max_file_bytes = 500
80 80
81 81 id_, params = build_data(
82 82 self.apikey, 'get_repo_nodes',
83 83 repoid=backend.repo_name, revision=commit_id, details='full',
84 84 root_path=path)
85 85 response = api_call(self.app, params)
86 86 assert any(file['content'] and len(file['content']) > max_file_bytes
87 87 for file in response.json['result'])
88 88
89 89 id_, params = build_data(
90 90 self.apikey, 'get_repo_nodes',
91 91 repoid=backend.repo_name, revision=commit_id,
92 92 root_path=path, details='full',
93 93 max_file_bytes=max_file_bytes)
94 94 response = api_call(self.app, params)
95 95 assert all(
96 96 file['content'] is None if file['size'] > max_file_bytes else True
97 97 for file in response.json['result'])
98 98
99 99 def test_api_get_repo_nodes_bad_ret_type(self, backend):
100 100 commit_id = 'tip'
101 101 path = '/'
102 102 ret_type = 'error'
103 103 id_, params = build_data(
104 104 self.apikey, 'get_repo_nodes',
105 105 repoid=backend.repo_name, revision=commit_id,
106 106 root_path=path,
107 107 ret_type=ret_type)
108 108 response = api_call(self.app, params)
109 109
110 110 expected = ('ret_type must be one of %s'
111 111 % (','.join(['all', 'dirs', 'files'])))
112 112 assert_error(id_, expected, given=response.body)
113 113
114 114 @pytest.mark.parametrize("name, ret_type, grant_perm", [
115 115 ('all', 'all', 'repository.write'),
116 116 ('dirs', 'dirs', 'repository.admin'),
117 117 ('files', 'files', 'repository.read'),
118 118 ])
119 119 def test_api_get_repo_nodes_by_regular_user(
120 120 self, name, ret_type, grant_perm, backend):
121 121 RepoModel().grant_user_permission(repo=backend.repo_name,
122 122 user=self.TEST_USER_LOGIN,
123 123 perm=grant_perm)
124 124 Session().commit()
125 125
126 126 commit_id = 'tip'
127 127 path = '/'
128 128 id_, params = build_data(
129 129 self.apikey_regular, 'get_repo_nodes',
130 130 repoid=backend.repo_name, revision=commit_id,
131 131 root_path=path,
132 132 ret_type=ret_type)
133 133 response = api_call(self.app, params)
134 134
135 135 # we don't the actual return types here since it's tested somewhere
136 136 # else
137 137 expected = response.json['result']
138 138 try:
139 139 assert_ok(id_, expected, given=response.body)
140 140 finally:
141 141 RepoModel().revoke_user_permission(
142 142 backend.repo_name, self.TEST_USER_LOGIN)
@@ -1,40 +1,40 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.meta import Session
25 25 from rhodecode.model.repo import RepoModel
26 26 from rhodecode.model.user import UserModel
27 27 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
28 28 from rhodecode.api.tests.utils import (
29 29 build_data, api_call, assert_ok, assert_error, expected_permissions)
30 30
31 31
32 32 @pytest.mark.usefixtures("testuser_api", "app")
33 33 class TestGetRepo(object):
34 34 def test_api_get_repo_refs(self, backend, user_util):
35 35 repo = backend.create_repo()
36 36 id_, params = build_data(self.apikey, 'get_repo_refs',
37 37 **{'repoid': repo.repo_name,})
38 38 response = api_call(self.app, params)
39 39 expected = repo.scm_instance().refs()
40 40 assert_ok(id_, expected, given=response.body)
@@ -1,58 +1,129 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.repo import RepoModel
25 from rhodecode.api.tests.utils import build_data, api_call, assert_ok, jsonify
25 from rhodecode.api.tests.utils import (
26 build_data, api_call, assert_ok, assert_error, jsonify)
26 27 from rhodecode.model.db import User
27 28
28 29
29 30 @pytest.mark.usefixtures("testuser_api", "app")
30 31 class TestGetRepos(object):
31 32 def test_api_get_repos(self):
32 33 id_, params = build_data(self.apikey, 'get_repos')
33 34 response = api_call(self.app, params)
34 35
35 36 result = []
36 37 for repo in RepoModel().get_all():
37 38 result.append(repo.get_api_data(include_secrets=True))
38 39 ret = jsonify(result)
39 40
40 41 expected = ret
41 42 assert_ok(id_, expected, given=response.body)
42 43
44 def test_api_get_repos_only_toplevel(self, user_util):
45 repo_group = user_util.create_repo_group(auto_cleanup=True)
46 user_util.create_repo(parent=repo_group)
47
48 id_, params = build_data(self.apikey, 'get_repos', traverse=0)
49 response = api_call(self.app, params)
50
51 result = []
52 for repo in RepoModel().get_repos_for_root(root=None):
53 result.append(repo.get_api_data(include_secrets=True))
54 expected = jsonify(result)
55
56 assert_ok(id_, expected, given=response.body)
57
58 def test_api_get_repos_with_wrong_root(self):
59 id_, params = build_data(self.apikey, 'get_repos', root='abracadabra')
60 response = api_call(self.app, params)
61
62 expected = 'Root repository group `abracadabra` does not exist'
63 assert_error(id_, expected, given=response.body)
64
65 def test_api_get_repos_with_root(self, user_util):
66 repo_group = user_util.create_repo_group(auto_cleanup=True)
67 repo_group_name = repo_group.group_name
68
69 user_util.create_repo(parent=repo_group)
70 user_util.create_repo(parent=repo_group)
71
72 # nested, should not show up
73 user_util._test_name = '{}/'.format(repo_group_name)
74 sub_repo_group = user_util.create_repo_group(auto_cleanup=True)
75 user_util.create_repo(parent=sub_repo_group)
76
77 id_, params = build_data(self.apikey, 'get_repos',
78 root=repo_group_name, traverse=0)
79 response = api_call(self.app, params)
80
81 result = []
82 for repo in RepoModel().get_repos_for_root(repo_group):
83 result.append(repo.get_api_data(include_secrets=True))
84
85 assert len(result) == 2
86 expected = jsonify(result)
87 assert_ok(id_, expected, given=response.body)
88
89 def test_api_get_repos_with_root_and_traverse(self, user_util):
90 repo_group = user_util.create_repo_group(auto_cleanup=True)
91 repo_group_name = repo_group.group_name
92
93 user_util.create_repo(parent=repo_group)
94 user_util.create_repo(parent=repo_group)
95
96 # nested, should not show up
97 user_util._test_name = '{}/'.format(repo_group_name)
98 sub_repo_group = user_util.create_repo_group(auto_cleanup=True)
99 user_util.create_repo(parent=sub_repo_group)
100
101 id_, params = build_data(self.apikey, 'get_repos',
102 root=repo_group_name, traverse=1)
103 response = api_call(self.app, params)
104
105 result = []
106 for repo in RepoModel().get_repos_for_root(
107 repo_group_name, traverse=True):
108 result.append(repo.get_api_data(include_secrets=True))
109
110 assert len(result) == 3
111 expected = jsonify(result)
112 assert_ok(id_, expected, given=response.body)
113
43 114 def test_api_get_repos_non_admin(self):
44 115 id_, params = build_data(self.apikey_regular, 'get_repos')
45 116 response = api_call(self.app, params)
46 117
47 118 user = User.get_by_username(self.TEST_USER_LOGIN)
48 119 allowed_repos = user.AuthUser.permissions['repositories']
49 120
50 121 result = []
51 122 for repo in RepoModel().get_all():
52 123 perm = allowed_repos[repo.repo_name]
53 124 if perm in ['repository.read', 'repository.write', 'repository.admin']:
54 125 result.append(repo.get_api_data())
55 126 ret = jsonify(result)
56 127
57 128 expected = ret
58 129 assert_ok(id_, expected, given=response.body)
@@ -1,84 +1,84 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import pytest
23 23
24 24 from rhodecode.model.scm import ScmModel
25 25 from rhodecode.api.tests.utils import build_data, api_call, assert_ok
26 26
27 27
28 28 @pytest.fixture
29 29 def http_host_stub():
30 30 """
31 31 To ensure that we can get an IP address, this test shall run with a
32 32 hostname set to "localhost".
33 33 """
34 34 return 'localhost:80'
35 35
36 36
37 37 @pytest.mark.usefixtures("testuser_api", "app")
38 38 class TestGetServerInfo(object):
39 39 def test_api_get_server_info(self):
40 40 id_, params = build_data(self.apikey, 'get_server_info')
41 41 response = api_call(self.app, params)
42 42 resp = response.json
43 43 expected = ScmModel().get_server_info()
44 44 expected['memory'] = resp['result']['memory']
45 45 expected['uptime'] = resp['result']['uptime']
46 46 expected['load'] = resp['result']['load']
47 47 expected['cpu'] = resp['result']['cpu']
48 48 expected['storage'] = resp['result']['storage']
49 49 expected['storage_temp'] = resp['result']['storage_temp']
50 50 expected['storage_inodes'] = resp['result']['storage_inodes']
51 51 expected['server'] = resp['result']['server']
52 52
53 53 expected['index_storage'] = resp['result']['index_storage']
54 54 expected['storage'] = resp['result']['storage']
55 55
56 56 assert_ok(id_, expected, given=response.body)
57 57
58 58 def test_api_get_server_info_ip(self):
59 59 id_, params = build_data(self.apikey, 'get_server_info')
60 60 response = api_call(self.app, params)
61 61 resp = response.json
62 62 expected = ScmModel().get_server_info({'SERVER_NAME': 'unknown'})
63 63 expected['memory'] = resp['result']['memory']
64 64 expected['uptime'] = resp['result']['uptime']
65 65 expected['load'] = resp['result']['load']
66 66 expected['cpu'] = resp['result']['cpu']
67 67 expected['storage'] = resp['result']['storage']
68 68 expected['storage_temp'] = resp['result']['storage_temp']
69 69 expected['storage_inodes'] = resp['result']['storage_inodes']
70 70 expected['server'] = resp['result']['server']
71 71
72 72 expected['index_storage'] = resp['result']['index_storage']
73 73 expected['storage'] = resp['result']['storage']
74 74
75 75 assert_ok(id_, expected, given=response.body)
76 76
77 77 def test_api_get_server_info_data_for_search_index_build(self):
78 78 id_, params = build_data(self.apikey, 'get_server_info')
79 79 response = api_call(self.app, params)
80 80 resp = response.json
81 81
82 82 # required by indexer
83 83 assert resp['result']['index_storage']
84 84 assert resp['result']['storage']
@@ -1,80 +1,80 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.lib.auth import AuthUser
24 24 from rhodecode.model.user import UserModel
25 25 from rhodecode.tests import TEST_USER_ADMIN_LOGIN
26 26 from rhodecode.api.tests.utils import (
27 27 build_data, api_call, assert_ok, assert_error)
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestGetUser(object):
32 32 def test_api_get_user(self):
33 33 id_, params = build_data(
34 34 self.apikey, 'get_user', userid=TEST_USER_ADMIN_LOGIN)
35 35 response = api_call(self.app, params)
36 36
37 37 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
38 38 ret = usr.get_api_data(include_secrets=True)
39 39 ret['permissions'] = AuthUser(usr.user_id).permissions
40 40
41 41 expected = ret
42 42 assert_ok(id_, expected, given=response.body)
43 43
44 44 def test_api_get_user_not_existing(self):
45 45 id_, params = build_data(self.apikey, 'get_user', userid='trololo')
46 46 response = api_call(self.app, params)
47 47
48 48 expected = "user `%s` does not exist" % 'trololo'
49 49 assert_error(id_, expected, given=response.body)
50 50
51 51 def test_api_get_user_without_giving_userid(self):
52 52 id_, params = build_data(self.apikey, 'get_user')
53 53 response = api_call(self.app, params)
54 54
55 55 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
56 56 ret = usr.get_api_data(include_secrets=True)
57 57 ret['permissions'] = AuthUser(usr.user_id).permissions
58 58
59 59 expected = ret
60 60 assert_ok(id_, expected, given=response.body)
61 61
62 62 def test_api_get_user_without_giving_userid_non_admin(self):
63 63 id_, params = build_data(self.apikey_regular, 'get_user')
64 64 response = api_call(self.app, params)
65 65
66 66 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
67 67 ret = usr.get_api_data(include_secrets=True)
68 68 ret['permissions'] = AuthUser(usr.user_id).permissions
69 69
70 70 expected = ret
71 71 assert_ok(id_, expected, given=response.body)
72 72
73 73 def test_api_get_user_with_giving_userid_non_admin(self):
74 74 id_, params = build_data(
75 75 self.apikey_regular, 'get_user',
76 76 userid=self.TEST_USER_LOGIN)
77 77 response = api_call(self.app, params)
78 78
79 79 expected = 'userid is not the same as your user'
80 80 assert_error(id_, expected, given=response.body)
@@ -1,74 +1,74 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.user import UserModel
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_ok, assert_error, expected_permissions)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestGetUserGroups(object):
30 30 def test_api_get_user_group(self, user_util):
31 31 user, group = user_util.create_user_with_group()
32 32 id_, params = build_data(
33 33 self.apikey, 'get_user_group', usergroupid=group.users_group_name)
34 34 response = api_call(self.app, params)
35 35
36 36 ret = group.get_api_data()
37 37 ret['users'] = [user.get_api_data()]
38 38
39 39 permissions = expected_permissions(group)
40 40
41 41 ret['members'] = permissions
42 42 expected = ret
43 43 assert_ok(id_, expected, given=response.body)
44 44
45 45 def test_api_get_user_group_regular_user(self, user_util):
46 46 user, group = user_util.create_user_with_group()
47 47 id_, params = build_data(
48 48 self.apikey_regular, 'get_user_group',
49 49 usergroupid=group.users_group_name)
50 50 response = api_call(self.app, params)
51 51
52 52 ret = group.get_api_data()
53 53 ret['users'] = [user.get_api_data()]
54 54
55 55 permissions = expected_permissions(group)
56 56
57 57 ret['members'] = permissions
58 58 expected = ret
59 59 assert_ok(id_, expected, given=response.body)
60 60
61 61 def test_api_get_user_group_regular_user_permission_denied(
62 62 self, user_util):
63 63 group = user_util.create_user_group()
64 64 user = UserModel().get_by_username(self.TEST_USER_LOGIN)
65 65 group_name = group.users_group_name
66 66 user_util.grant_user_permission_to_user_group(
67 67 group, user, 'usergroup.none')
68 68
69 69 id_, params = build_data(
70 70 self.apikey_regular, 'get_user_group', usergroupid=group_name)
71 71 response = api_call(self.app, params)
72 72
73 73 expected = 'user group `%s` does not exist' % (group_name,)
74 74 assert_error(id_, expected, given=response.body)
@@ -1,71 +1,71 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21
22 22 import json
23 23
24 24 import pytest
25 25
26 26 from rhodecode.model.user import UserModel
27 27 from rhodecode.api.tests.utils import build_data, api_call
28 28
29 29
30 30 @pytest.mark.usefixtures("testuser_api", "app")
31 31 class TestGetUserGroups(object):
32 32 @pytest.mark.parametrize("apikey_attr, expect_secrets", [
33 33 ('apikey', True),
34 34 ('apikey_regular', False),
35 35 ])
36 36 def test_api_get_user_groups(self, apikey_attr, expect_secrets, user_util):
37 37 first_group = user_util.create_user_group()
38 38 second_group = user_util.create_user_group()
39 39 expected = [
40 40 g.get_api_data(include_secrets=expect_secrets)
41 41 for g in (first_group, second_group)]
42 42
43 43 apikey = getattr(self, apikey_attr)
44 44 id_, params = build_data(apikey, 'get_user_groups', )
45 45 response = api_call(self.app, params)
46 46 self._assert_ok(id_, expected, response)
47 47
48 48 def test_api_get_user_groups_regular_user(self, user_util):
49 49 first_group = user_util.create_user_group()
50 50 second_group = user_util.create_user_group()
51 51 expected = [g.get_api_data() for g in (first_group, second_group)]
52 52
53 53 id_, params = build_data(self.apikey_regular, 'get_user_groups', )
54 54 response = api_call(self.app, params)
55 55 self._assert_ok(id_, expected, response)
56 56
57 57 def test_api_get_user_groups_regular_user_no_permission(self, user_util):
58 58 group = user_util.create_user_group()
59 59 user = UserModel().get_by_username(self.TEST_USER_LOGIN)
60 60 user_util.grant_user_permission_to_user_group(
61 61 group, user, 'usergroup.none')
62 62 id_, params = build_data(self.apikey_regular, 'get_user_groups', )
63 63 response = api_call(self.app, params)
64 64 expected = []
65 65 self._assert_ok(id_, expected, response)
66 66
67 67 def _assert_ok(self, id_, expected_list, response):
68 68 result = json.loads(response.body)
69 69 assert result['id'] == id_
70 70 assert result['error'] is None
71 71 assert sorted(result['result']) == sorted(expected_list)
@@ -1,40 +1,40 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
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
21 21 import pytest
22 22
23 23 from rhodecode.model.db import User
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_ok, jsonify)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestGetUsers(object):
30 30 def test_api_get_users(self):
31 31 id_, params = build_data(self.apikey, 'get_users', )
32 32 response = api_call(self.app, params)
33 33 ret_all = []
34 34 _users = User.query().filter(User.username != User.DEFAULT_USER) \
35 35 .order_by(User.username).all()
36 36 for usr in _users:
37 37 ret = usr.get_api_data(include_secrets=True)
38 38 ret_all.append(jsonify(ret))
39 39 expected = ret_all
40 40 assert_ok(id_, expected, given=response.body)
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full 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/templates/admin/admin.html to rhodecode/templates/admin/admin.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/admin_log.html to rhodecode/templates/admin/admin_log.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/auth/auth_settings.html to rhodecode/templates/admin/auth/auth_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/auth/plugin_settings.html to rhodecode/templates/admin/auth/plugin_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/defaults/defaults.html to rhodecode/templates/admin/defaults/defaults.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/defaults/defaults_repositories.html to rhodecode/templates/admin/defaults/defaults_repositories.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/gists/edit.html to rhodecode/templates/admin/gists/edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/gists/index.html to rhodecode/templates/admin/gists/index.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/gists/new.html to rhodecode/templates/admin/gists/new.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/gists/show.html to rhodecode/templates/admin/gists/show.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/integrations/base.html to rhodecode/templates/admin/integrations/base.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/integrations/form.html to rhodecode/templates/admin/integrations/form.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/integrations/list.html to rhodecode/templates/admin/integrations/list.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/integrations/new.html to rhodecode/templates/admin/integrations/new.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account.html to rhodecode/templates/admin/my_account/my_account.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_auth_tokens.html to rhodecode/templates/admin/my_account/my_account_auth_tokens.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_emails.html to rhodecode/templates/admin/my_account/my_account_emails.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_notifications.html to rhodecode/templates/admin/my_account/my_account_notifications.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_password.html to rhodecode/templates/admin/my_account/my_account_password.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_perms.html to rhodecode/templates/admin/my_account/my_account_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_profile.html to rhodecode/templates/admin/my_account/my_account_profile.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_profile_edit.html to rhodecode/templates/admin/my_account/my_account_profile_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_pullrequests.html to rhodecode/templates/admin/my_account/my_account_pullrequests.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_repos.html to rhodecode/templates/admin/my_account/my_account_repos.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/my_account/my_account_watched.html to rhodecode/templates/admin/my_account/my_account_watched.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/notifications/notifications.html to rhodecode/templates/admin/notifications/notifications.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/notifications/notifications_data.html to rhodecode/templates/admin/notifications/notifications_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/notifications/show_notification.html to rhodecode/templates/admin/notifications/show_notification.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions.html to rhodecode/templates/admin/permissions/permissions.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions_application.html to rhodecode/templates/admin/permissions/permissions_application.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions_global.html to rhodecode/templates/admin/permissions/permissions_global.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions_ips.html to rhodecode/templates/admin/permissions/permissions_ips.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions_objects.html to rhodecode/templates/admin/permissions/permissions_objects.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/permissions/permissions_perms.html to rhodecode/templates/admin/permissions/permissions_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_group_add.html to rhodecode/templates/admin/repo_groups/repo_group_add.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_group_edit.html to rhodecode/templates/admin/repo_groups/repo_group_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_group_edit_advanced.html to rhodecode/templates/admin/repo_groups/repo_group_edit_advanced.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_group_edit_perms.html to rhodecode/templates/admin/repo_groups/repo_group_edit_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_group_edit_settings.html to rhodecode/templates/admin/repo_groups/repo_group_edit_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repo_groups/repo_groups.html to rhodecode/templates/admin/repo_groups/repo_groups.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_add.html to rhodecode/templates/admin/repos/repo_add.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_add_base.html to rhodecode/templates/admin/repos/repo_add_base.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_creating.html to rhodecode/templates/admin/repos/repo_creating.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit.html to rhodecode/templates/admin/repos/repo_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_advanced.html to rhodecode/templates/admin/repos/repo_edit_advanced.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_caches.html to rhodecode/templates/admin/repos/repo_edit_caches.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_fields.html to rhodecode/templates/admin/repos/repo_edit_fields.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_fork.html to rhodecode/templates/admin/repos/repo_edit_fork.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_issuetracker.html to rhodecode/templates/admin/repos/repo_edit_issuetracker.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_permissions.html to rhodecode/templates/admin/repos/repo_edit_permissions.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_remote.html to rhodecode/templates/admin/repos/repo_edit_remote.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_settings.html to rhodecode/templates/admin/repos/repo_edit_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_statistics.html to rhodecode/templates/admin/repos/repo_edit_statistics.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repo_edit_vcs.html to rhodecode/templates/admin/repos/repo_edit_vcs.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/repos/repos.html to rhodecode/templates/admin/repos/repos.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings.html to rhodecode/templates/admin/settings/settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_email.html to rhodecode/templates/admin/settings/settings_email.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_global.html to rhodecode/templates/admin/settings/settings_global.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_hooks.html to rhodecode/templates/admin/settings/settings_hooks.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_issuetracker.html to rhodecode/templates/admin/settings/settings_issuetracker.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_labs.html to rhodecode/templates/admin/settings/settings_labs.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_mapping.html to rhodecode/templates/admin/settings/settings_mapping.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_open_source.html to rhodecode/templates/admin/settings/settings_open_source.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_search.html to rhodecode/templates/admin/settings/settings_search.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_supervisor.html to rhodecode/templates/admin/settings/settings_supervisor.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_supervisor_tail.html to rhodecode/templates/admin/settings/settings_supervisor_tail.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_system.html to rhodecode/templates/admin/settings/settings_system.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_system_snapshot.html to rhodecode/templates/admin/settings/settings_system_snapshot.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_system_update.html to rhodecode/templates/admin/settings/settings_system_update.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_vcs.html to rhodecode/templates/admin/settings/settings_vcs.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/settings/settings_visual.html to rhodecode/templates/admin/settings/settings_visual.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_add.html to rhodecode/templates/admin/user_groups/user_group_add.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit.html to rhodecode/templates/admin/user_groups/user_group_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit_advanced.html to rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit_global_perms.html to rhodecode/templates/admin/user_groups/user_group_edit_global_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit_perms.html to rhodecode/templates/admin/user_groups/user_group_edit_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit_perms_summary.html to rhodecode/templates/admin/user_groups/user_group_edit_perms_summary.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_group_edit_settings.html to rhodecode/templates/admin/user_groups/user_group_edit_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/user_groups/user_groups.html to rhodecode/templates/admin/user_groups/user_groups.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_add.html to rhodecode/templates/admin/users/user_add.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit.html to rhodecode/templates/admin/users/user_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_advanced.html to rhodecode/templates/admin/users/user_edit_advanced.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_auth_tokens.html to rhodecode/templates/admin/users/user_edit_auth_tokens.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_emails.html to rhodecode/templates/admin/users/user_edit_emails.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_global_perms.html to rhodecode/templates/admin/users/user_edit_global_perms.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_ips.html to rhodecode/templates/admin/users/user_edit_ips.mako
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_perms_summary.html to rhodecode/templates/admin/users/user_edit_perms_summary.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/user_edit_profile.html to rhodecode/templates/admin/users/user_edit_profile.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/admin/users/users.html to rhodecode/templates/admin/users/users.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/base.html to rhodecode/templates/base/base.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/default_perms_box.html to rhodecode/templates/base/default_perms_box.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/issue_tracker_settings.html to rhodecode/templates/base/issue_tracker_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/perms_summary.html to rhodecode/templates/base/perms_summary.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/plugins_base.html to rhodecode/templates/base/plugins_base.mako
1 NO CONTENT: file renamed from rhodecode/templates/base/root.html to rhodecode/templates/base/root.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/base/vcs_settings.html to rhodecode/templates/base/vcs_settings.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/bookmarks/bookmarks.html to rhodecode/templates/bookmarks/bookmarks.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/bookmarks/bookmarks_data.html to rhodecode/templates/bookmarks/bookmarks_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/branches/branches.html to rhodecode/templates/branches/branches.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/branches/branches_data.html to rhodecode/templates/branches/branches_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog.html to rhodecode/templates/changelog/changelog.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_details.html to rhodecode/templates/changelog/changelog_elements.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_file_history.html to rhodecode/templates/changelog/changelog_file_history.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changelog/changelog_summary_data.html to rhodecode/templates/changelog/changelog_summary_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/changeset.html to rhodecode/templates/changeset/changeset.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/changeset_comment_block.html to rhodecode/templates/changeset/changeset_comment_block.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/changeset_file_comment.html to rhodecode/templates/changeset/changeset_file_comment.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/changeset_range.html to rhodecode/templates/changeset/changeset_range.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/diff_block.html to rhodecode/templates/changeset/diff_block.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/changeset/patch_changeset.html to rhodecode/templates/changeset/patch_changeset.mako
1 NO CONTENT: file renamed from rhodecode/templates/channelstream/plugin_init.html to rhodecode/templates/channelstream/plugin_init.mako
1 NO CONTENT: file renamed from rhodecode/templates/codeblocks/diffs.html to rhodecode/templates/codeblocks/diffs.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/codeblocks/source.html to rhodecode/templates/codeblocks/source.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/compare/compare_commits.html to rhodecode/templates/compare/compare_commits.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/compare/compare_diff.html to rhodecode/templates/compare/compare_diff.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/data_table/_dt_elements.html to rhodecode/templates/data_table/_dt_elements.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full 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/templates/errors/error_document.html to rhodecode/templates/errors/error_document.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/base.html to rhodecode/templates/files/base.mako
1 NO CONTENT: file renamed from rhodecode/templates/files/file_authors_box.html to rhodecode/templates/files/file_authors_box.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/file_tree_author_box.html to rhodecode/templates/files/file_tree_author_box.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/file_tree_detail.html to rhodecode/templates/files/file_tree_detail.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files.html to rhodecode/templates/files/files.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_add.html to rhodecode/templates/files/files_add.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_browser.html to rhodecode/templates/files/files_browser.mako
1 NO CONTENT: file renamed from rhodecode/templates/files/files_browser_tree.html to rhodecode/templates/files/files_browser_tree.mako
1 NO CONTENT: file renamed from rhodecode/templates/files/files_delete.html to rhodecode/templates/files/files_delete.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_detail.html to rhodecode/templates/files/files_detail.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_edit.html to rhodecode/templates/files/files_edit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_pjax.html to rhodecode/templates/files/files_pjax.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/files/files_source.html to rhodecode/templates/files/files_source.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/followers/followers.html to rhodecode/templates/followers/followers.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/followers/followers_data.html to rhodecode/templates/followers/followers_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/forks/fork.html to rhodecode/templates/forks/fork.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/forks/forks.html to rhodecode/templates/forks/forks.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/forks/forks_data.html to rhodecode/templates/forks/forks_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/index.html to rhodecode/templates/index.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/index_base.html to rhodecode/templates/index_base.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/index_repo_group.html to rhodecode/templates/index_repo_group.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/journal/journal.html to rhodecode/templates/journal/journal.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/journal/journal_data.html to rhodecode/templates/journal/journal_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/journal/public_journal.html to rhodecode/templates/journal/public_journal.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/login.html to rhodecode/templates/login.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/password_reset.html to rhodecode/templates/password_reset.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/pullrequests/pullrequest.html to rhodecode/templates/pullrequests/pullrequest.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/pullrequests/pullrequest_show.html to rhodecode/templates/pullrequests/pullrequest_show.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/pullrequests/pullrequests.html to rhodecode/templates/pullrequests/pullrequests.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/register.html to rhodecode/templates/register.mako
The requested commit or file is too big and content was truncated. Show full 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/templates/search/search.html to rhodecode/templates/search/search.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/search/search_commit.html to rhodecode/templates/search/search_commit.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/search/search_content.html to rhodecode/templates/search/search_content.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/search/search_path.html to rhodecode/templates/search/search_path.mako
1 NO CONTENT: file renamed from rhodecode/templates/search/search_repository.html to rhodecode/templates/search/search_repository.mako
1 NO CONTENT: file renamed from rhodecode/templates/summary/base.html to rhodecode/templates/summary/base.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/summary/components.html to rhodecode/templates/summary/components.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/summary/missing_requirements.html to rhodecode/templates/summary/missing_requirements.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/summary/summary.html to rhodecode/templates/summary/summary.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/tags/tags.html to rhodecode/templates/tags/tags.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/tags/tags_data.html to rhodecode/templates/tags/tags_data.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/users/user.html to rhodecode/templates/users/user.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/users/user_profile.html to rhodecode/templates/users/user_profile.mako
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/templates/widgets.html to rhodecode/templates/widgets.mako
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full 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
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
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
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
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