Show More
@@ -0,0 +1,17 b'' | |||||
|
1 | |RCE| 4.0.1 |RNS| | |||
|
2 | ----------------- | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2016-05-25 | |||
|
8 | ||||
|
9 | Fixes | |||
|
10 | ^^^^^ | |||
|
11 | ||||
|
12 | - fixed default session to be file based instead of memory which causes | |||
|
13 | problems in multi-worker setup | |||
|
14 | - ui: fixing forks table #3959 | |||
|
15 | - ui: fixed gravatars misalignment issues | |||
|
16 | - logging: fixed excesive formatting on auth logging | |||
|
17 | - pull requests: better ref selection when opening PRs from changelog |
@@ -1,5 +1,6 b'' | |||||
1 | [bumpversion] |
|
1 | [bumpversion] | |
2 |
current_version = 4.0. |
|
2 | current_version = 4.0.1 | |
3 | message = release: Bump version {current_version} to {new_version} |
|
3 | message = release: Bump version {current_version} to {new_version} | |
4 |
|
4 | |||
5 | [bumpversion:file:rhodecode/VERSION] |
|
5 | [bumpversion:file:rhodecode/VERSION] | |
|
6 |
@@ -5,10 +5,17 b' NODE_PATH=./node_modules' | |||||
5 | FLAKE8=flake8 setup.py pytest_pylons/ rhodecode/ --select=E124 --ignore=E711,E712,E510,E121,E122,E126,E127,E128,E501,F401 --max-line-length=100 --exclude=*rhodecode/lib/dbmigrate/*,*rhodecode/tests/*,*rhodecode/lib/vcs/utils/* |
|
5 | FLAKE8=flake8 setup.py pytest_pylons/ rhodecode/ --select=E124 --ignore=E711,E712,E510,E121,E122,E126,E127,E128,E501,F401 --max-line-length=100 --exclude=*rhodecode/lib/dbmigrate/*,*rhodecode/tests/*,*rhodecode/lib/vcs/utils/* | |
6 | CI_PREFIX=enterprise |
|
6 | CI_PREFIX=enterprise | |
7 |
|
7 | |||
8 |
.PHONY: |
|
8 | .PHONY: docs docs-clean ci-docs clean test test-clean test-lint test-only | |
|
9 | ||||
|
10 | ||||
|
11 | docs: | |||
|
12 | (cd docs; nix-build default.nix -o result; make clean html) | |||
9 |
|
|
13 | ||
10 | help: |
|
14 | docs-clean: | |
11 | @echo "TODO: describe Makefile" |
|
15 | (cd docs; make clean) | |
|
16 | ||||
|
17 | ci-docs: docs; | |||
|
18 | ||||
12 |
|
19 | |||
13 | clean: test-clean |
|
20 | clean: test-clean | |
14 | find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';' |
|
21 | find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';' | |
@@ -37,3 +44,4 b' web-test:' | |||||
37 | docs-bootstrap: |
|
44 | docs-bootstrap: | |
38 | (cd docs; nix-build default.nix -o result) |
|
45 | (cd docs; nix-build default.nix -o result) | |
39 | @echo "Please go to docs folder and run make html" |
|
46 | @echo "Please go to docs folder and run make html" | |
|
47 |
@@ -65,6 +65,8 b' asyncore_use_poll = true' | |||||
65 | ## type of worker class, one of sync, gevent |
|
65 | ## type of worker class, one of sync, gevent | |
66 | ## recommended for bigger setup is using of of other than sync one |
|
66 | ## recommended for bigger setup is using of of other than sync one | |
67 | #worker_class = sync |
|
67 | #worker_class = sync | |
|
68 | ## The maximum number of simultaneous clients. Valid only for Gevent | |||
|
69 | #worker_connections = 10 | |||
68 | ## max number of requests that worker will handle before being gracefully |
|
70 | ## max number of requests that worker will handle before being gracefully | |
69 | ## restarted, could prevent memory leaks |
|
71 | ## restarted, could prevent memory leaks | |
70 | #max_requests = 1000 |
|
72 | #max_requests = 1000 |
@@ -65,6 +65,8 b' asyncore_use_poll = true' | |||||
65 | ## type of worker class, one of sync, gevent |
|
65 | ## type of worker class, one of sync, gevent | |
66 | ## recommended for bigger setup is using of of other than sync one |
|
66 | ## recommended for bigger setup is using of of other than sync one | |
67 | #worker_class = sync |
|
67 | #worker_class = sync | |
|
68 | ## The maximum number of simultaneous clients. Valid only for Gevent | |||
|
69 | #worker_connections = 10 | |||
68 | ## max number of requests that worker will handle before being gracefully |
|
70 | ## max number of requests that worker will handle before being gracefully | |
69 | ## restarted, could prevent memory leaks |
|
71 | ## restarted, could prevent memory leaks | |
70 | #max_requests = 1000 |
|
72 | #max_requests = 1000 | |
@@ -288,12 +290,12 b' beaker.cache.repo_cache_long.expire = 25' | |||||
288 | #################################### |
|
290 | #################################### | |
289 |
|
291 | |||
290 | ## .session.type is type of storage options for the session, current allowed |
|
292 | ## .session.type is type of storage options for the session, current allowed | |
291 |
## types are file |
|
293 | ## types are file, ext:memcached, ext:database, and memory(default). | |
292 |
|
|
294 | beaker.session.type = file | |
|
295 | beaker.session.data_dir = %(here)s/data/sessions/data | |||
293 |
|
296 | |||
294 | ## db based session, fast, and allows easy management over logged in users ## |
|
297 | ## db based session, fast, and allows easy management over logged in users ## | |
295 | #beaker.session.type = ext:database |
|
298 | #beaker.session.type = ext:database | |
296 | #beaker.session.lock_dir = %(here)s/data/cache/session_db_lock |
|
|||
297 | #beaker.session.table_name = db_session |
|
299 | #beaker.session.table_name = db_session | |
298 | #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode |
|
300 | #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode | |
299 | #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode |
|
301 | #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode | |
@@ -302,6 +304,7 b' beaker.cache.repo_cache_long.expire = 25' | |||||
302 |
|
304 | |||
303 | beaker.session.key = rhodecode |
|
305 | beaker.session.key = rhodecode | |
304 | beaker.session.secret = production-rc-uytcxaz |
|
306 | beaker.session.secret = production-rc-uytcxaz | |
|
307 | #beaker.session.lock_dir = %(here)s/data/sessions/lock | |||
305 |
|
308 | |||
306 | ## Secure encrypted cookie. Requires AES and AES python libraries |
|
309 | ## Secure encrypted cookie. Requires AES and AES python libraries | |
307 | ## you must disable beaker.session.secret to use this |
|
310 | ## you must disable beaker.session.secret to use this | |
@@ -435,6 +438,13 b' vcs.server.enable = true' | |||||
435 | vcs.server = localhost:9900 |
|
438 | vcs.server = localhost:9900 | |
436 | # Available protocols: pyro4, http |
|
439 | # Available protocols: pyro4, http | |
437 | vcs.server.protocol = pyro4 |
|
440 | vcs.server.protocol = pyro4 | |
|
441 | ||||
|
442 | # available impl: | |||
|
443 | # vcsserver.scm_app (EE only, for testing), | |||
|
444 | # rhodecode.lib.middleware.utils.scm_app_http | |||
|
445 | # pyro4 | |||
|
446 | #vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http | |||
|
447 | ||||
438 | vcs.server.log_level = info |
|
448 | vcs.server.log_level = info | |
439 | vcs.start_server = false |
|
449 | vcs.start_server = false | |
440 | vcs.backends = hg, git, svn |
|
450 | vcs.backends = hg, git, svn |
@@ -6,6 +6,7 b' Release Notes' | |||||
6 | |RCE| 4.x Versions |
|
6 | |RCE| 4.x Versions | |
7 | ------------------ |
|
7 | ------------------ | |
8 |
|
8 | |||
|
9 | release-notes-4.0.1.rst | |||
9 | release-notes-4.0.0.rst |
|
10 | release-notes-4.0.0.rst | |
10 |
|
11 | |||
11 | |RCE| 3.x Versions |
|
12 | |RCE| 3.x Versions |
@@ -360,7 +360,7 b'' | |||||
360 | }; |
|
360 | }; | |
361 | }; |
|
361 | }; | |
362 | certifi = super.buildPythonPackage { |
|
362 | certifi = super.buildPythonPackage { | |
363 |
name = "certifi-2016. |
|
363 | name = "certifi-2016.2.28"; | |
364 | buildInputs = with self; []; |
|
364 | buildInputs = with self; []; | |
365 | doCheck = false; |
|
365 | doCheck = false; | |
366 | propagatedBuildInputs = with self; []; |
|
366 | propagatedBuildInputs = with self; []; | |
@@ -1050,10 +1050,10 b'' | |||||
1050 | }; |
|
1050 | }; | |
1051 | }; |
|
1051 | }; | |
1052 | rhodecode-enterprise-ce = super.buildPythonPackage { |
|
1052 | rhodecode-enterprise-ce = super.buildPythonPackage { | |
1053 |
name = "rhodecode-enterprise-ce-4.0. |
|
1053 | name = "rhodecode-enterprise-ce-4.0.1"; | |
1054 |
buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-runner |
|
1054 | buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; | |
1055 | doCheck = true; |
|
1055 | doCheck = true; | |
1056 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 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 waitress zope.cachedescriptors psutil py-bcrypt]; |
|
1056 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 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 waitress zope.cachedescriptors psutil py-bcrypt]; | |
1057 | src = ./.; |
|
1057 | src = ./.; | |
1058 | }; |
|
1058 | }; | |
1059 | rhodecode-tools = super.buildPythonPackage { |
|
1059 | rhodecode-tools = super.buildPythonPackage { |
@@ -36,7 +36,6 b' from sqlalchemy.ext.hybrid import hybrid' | |||||
36 | from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin |
|
36 | from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin | |
37 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase |
|
37 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
38 | from rhodecode.authentication.routes import AuthnPluginResourceBase |
|
38 | from rhodecode.authentication.routes import AuthnPluginResourceBase | |
39 | from rhodecode.lib.ext_json import formatted_json |
|
|||
40 | from rhodecode.lib.utils2 import safe_unicode |
|
39 | from rhodecode.lib.utils2 import safe_unicode | |
41 | from rhodecode.model.db import User |
|
40 | from rhodecode.model.db import User | |
42 |
|
41 | |||
@@ -119,17 +118,15 b' class RhodeCodeAuthPlugin(RhodeCodeExter' | |||||
119 | log.debug('Empty username or password skipping...') |
|
118 | log.debug('Empty username or password skipping...') | |
120 | return None |
|
119 | return None | |
121 |
|
120 | |||
122 |
log.debug("Jasig CAS settings: |
|
121 | log.debug("Jasig CAS settings: %s", settings) | |
123 | params = urllib.urlencode({'username': username, 'password': password}) |
|
122 | params = urllib.urlencode({'username': username, 'password': password}) | |
124 | headers = {"Content-type": "application/x-www-form-urlencoded", |
|
123 | headers = {"Content-type": "application/x-www-form-urlencoded", | |
125 | "Accept": "text/plain", |
|
124 | "Accept": "text/plain", | |
126 | "User-Agent": "RhodeCode-auth-%s" % rhodecode.__version__} |
|
125 | "User-Agent": "RhodeCode-auth-%s" % rhodecode.__version__} | |
127 | url = settings["service_url"] |
|
126 | url = settings["service_url"] | |
128 |
|
127 | |||
129 | log.debug("Sent Jasig CAS: \n%s" |
|
128 | log.debug("Sent Jasig CAS: \n%s", | |
130 | % (formatted_json({"url": url, |
|
129 | {"url": url, "body": params, "headers": headers}) | |
131 | "body": params, |
|
|||
132 | "headers": headers}))) |
|
|||
133 | request = urllib2.Request(url, params, headers) |
|
130 | request = urllib2.Request(url, params, headers) | |
134 | try: |
|
131 | try: | |
135 | response = urllib2.urlopen(request) |
|
132 | response = urllib2.urlopen(request) |
@@ -36,7 +36,6 b' from rhodecode.authentication.routes imp' | |||||
36 | from rhodecode.lib.exceptions import ( |
|
36 | from rhodecode.lib.exceptions import ( | |
37 | LdapConnectionError, LdapUsernameError, LdapPasswordError, LdapImportError |
|
37 | LdapConnectionError, LdapUsernameError, LdapPasswordError, LdapImportError | |
38 | ) |
|
38 | ) | |
39 | from rhodecode.lib.ext_json import formatted_json |
|
|||
40 | from rhodecode.lib.utils2 import safe_unicode, safe_str |
|
39 | from rhodecode.lib.utils2 import safe_unicode, safe_str | |
41 | from rhodecode.model.db import User |
|
40 | from rhodecode.model.db import User | |
42 | from rhodecode.model.validators import Missing |
|
41 | from rhodecode.model.validators import Missing | |
@@ -435,7 +434,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter' | |||||
435 | 'extern_name': user_dn, |
|
434 | 'extern_name': user_dn, | |
436 | 'extern_type': extern_type, |
|
435 | 'extern_type': extern_type, | |
437 | } |
|
436 | } | |
438 |
log.debug('ldap user: |
|
437 | log.debug('ldap user: %s', user_attrs) | |
439 | log.info('user %s authenticated correctly', user_attrs['username']) |
|
438 | log.info('user %s authenticated correctly', user_attrs['username']) | |
440 |
|
439 | |||
441 | return user_attrs |
|
440 | return user_attrs |
@@ -35,7 +35,6 b' from sqlalchemy.ext.hybrid import hybrid' | |||||
35 | from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin |
|
35 | from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin | |
36 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase |
|
36 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
37 | from rhodecode.authentication.routes import AuthnPluginResourceBase |
|
37 | from rhodecode.authentication.routes import AuthnPluginResourceBase | |
38 | from rhodecode.lib.ext_json import formatted_json |
|
|||
39 |
|
38 | |||
40 | log = logging.getLogger(__name__) |
|
39 | log = logging.getLogger(__name__) | |
41 |
|
40 | |||
@@ -151,6 +150,6 b' class RhodeCodeAuthPlugin(RhodeCodeExter' | |||||
151 | log.warning("Cannot extract additional info for PAM user") |
|
150 | log.warning("Cannot extract additional info for PAM user") | |
152 | pass |
|
151 | pass | |
153 |
|
152 | |||
154 |
log.debug("pamuser: |
|
153 | log.debug("pamuser: %s", user_attrs) | |
155 | log.info('user %s authenticated correctly' % user_attrs['username']) |
|
154 | log.info('user %s authenticated correctly' % user_attrs['username']) | |
156 | return user_attrs |
|
155 | return user_attrs |
@@ -133,7 +133,8 b' class SimpleVCS(object):' | |||||
133 | def is_valid_and_existing_repo(self, repo_name, base_path, scm_type): |
|
133 | def is_valid_and_existing_repo(self, repo_name, base_path, scm_type): | |
134 | db_repo = Repository.get_by_repo_name(repo_name) |
|
134 | db_repo = Repository.get_by_repo_name(repo_name) | |
135 | if not db_repo: |
|
135 | if not db_repo: | |
136 |
log.debug('Repository `%s` not found inside the database.' |
|
136 | log.debug('Repository `%s` not found inside the database.', | |
|
137 | repo_name) | |||
137 | return False |
|
138 | return False | |
138 |
|
139 | |||
139 | if db_repo.repo_type != scm_type: |
|
140 | if db_repo.repo_type != scm_type: |
@@ -1054,8 +1054,10 b' class PullRequestModel(BaseModel):' | |||||
1054 | ref_key = '%s:%s:%s' % (group_key, ref_name, ref_id) |
|
1054 | ref_key = '%s:%s:%s' % (group_key, ref_name, ref_id) | |
1055 | group_refs.append((ref_key, ref_name)) |
|
1055 | group_refs.append((ref_key, ref_name)) | |
1056 |
|
1056 | |||
1057 |
if not selected |
|
1057 | if not selected: | |
|
1058 | if set([commit_id, match]) & set([ref_id, ref_name]): | |||
1058 | selected = ref_key |
|
1059 | selected = ref_key | |
|
1060 | ||||
1059 | if group_refs: |
|
1061 | if group_refs: | |
1060 | groups.append((group_refs, group_name)) |
|
1062 | groups.append((group_refs, group_name)) | |
1061 |
|
1063 |
@@ -439,6 +439,11 b' div.codeblock {' | |||||
439 | padding: @padding; |
|
439 | padding: @padding; | |
440 | border-bottom: @border-thickness solid @grey5; |
|
440 | border-bottom: @border-thickness solid @grey5; | |
441 |
|
441 | |||
|
442 | .rc-user { | |||
|
443 | min-width: 0; | |||
|
444 | margin-right: .5em; | |||
|
445 | } | |||
|
446 | ||||
442 | .stats { |
|
447 | .stats { | |
443 | clear: both; |
|
448 | clear: both; | |
444 | margin: 0 0 @padding 0; |
|
449 | margin: 0 0 @padding 0; |
@@ -52,6 +52,11 b' tr.inline-comments div {' | |||||
52 | padding: 4px 0 0 0; |
|
52 | padding: 4px 0 0 0; | |
53 | line-height: 1em; |
|
53 | line-height: 1em; | |
54 |
|
54 | |||
|
55 | .rc-user { | |||
|
56 | min-width: 0; | |||
|
57 | margin: -2px .5em 0 0; | |||
|
58 | } | |||
|
59 | ||||
55 | .meta { |
|
60 | .meta { | |
56 | position: relative; |
|
61 | position: relative; | |
57 | width: 100%; |
|
62 | width: 100%; |
@@ -671,6 +671,7 b' label {' | |||||
671 | } |
|
671 | } | |
672 |
|
672 | |||
673 | .rc-user { // gravatar + user wrapper |
|
673 | .rc-user { // gravatar + user wrapper | |
|
674 | float: left; | |||
674 |
|
|
675 | position: relative; | |
675 | min-width: 100px; |
|
676 | min-width: 100px; | |
676 | max-width: 200px; |
|
677 | max-width: 200px; | |
@@ -1223,6 +1224,16 b' table.issuetracker {' | |||||
1223 | max-width: 83%; |
|
1224 | max-width: 83%; | |
1224 | padding-right: 20px; |
|
1225 | padding-right: 20px; | |
1225 | vertical-align: middle; |
|
1226 | vertical-align: middle; | |
|
1227 | line-height: 1; | |||
|
1228 | ||||
|
1229 | .rc-user { | |||
|
1230 | min-width: 0; | |||
|
1231 | margin: -2px 1em 0 0; | |||
|
1232 | } | |||
|
1233 | ||||
|
1234 | .reviewer { | |||
|
1235 | float: left; | |||
|
1236 | } | |||
1226 | } |
|
1237 | } | |
1227 |
|
1238 | |||
1228 | .reviewer_member_remove { |
|
1239 | .reviewer_member_remove { | |
@@ -1253,7 +1264,7 b' table.issuetracker {' | |||||
1253 | } |
|
1264 | } | |
1254 | .pr-details-content { |
|
1265 | .pr-details-content { | |
1255 | margin-top: @textmargin; |
|
1266 | margin-top: @textmargin; | |
1256 |
margin-bottom: @textmargin |
|
1267 | margin-bottom: @textmargin; | |
1257 | } |
|
1268 | } | |
1258 | .pr-description { |
|
1269 | .pr-description { | |
1259 | white-space:pre-wrap; |
|
1270 | white-space:pre-wrap; |
@@ -4,6 +4,7 b'' | |||||
4 | % if c.forks_pager: |
|
4 | % if c.forks_pager: | |
5 | <table class="rctable fork_summary"> |
|
5 | <table class="rctable fork_summary"> | |
6 | <tr> |
|
6 | <tr> | |
|
7 | <th>${_('Owner')}</th> | |||
7 | <th>${_('Fork')}</th> |
|
8 | <th>${_('Fork')}</th> | |
8 | <th>${_('Description')}</th> |
|
9 | <th>${_('Description')}</th> | |
9 | <th>${_('Forked')}</th> |
|
10 | <th>${_('Forked')}</th> | |
@@ -13,7 +14,8 b'' | |||||
13 | <tr> |
|
14 | <tr> | |
14 | <td class="td-user fork_user"> |
|
15 | <td class="td-user fork_user"> | |
15 | ${base.gravatar_with_user(f.user.email, 16)} |
|
16 | ${base.gravatar_with_user(f.user.email, 16)} | |
16 |
|
|
17 | </td> | |
|
18 | <td class="td-componentname"> | |||
17 | ${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))} |
|
19 | ${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))} | |
18 | </td> |
|
20 | </td> | |
19 | <td class="td-description"> |
|
21 | <td class="td-description"> |
@@ -195,9 +195,9 b'' | |||||
195 | <div class="reviewer_status tooltip" title="${h.tooltip(h.commit_status_lbl(status[0][1].status if status else 'not_reviewed'))}"> |
|
195 | <div class="reviewer_status tooltip" title="${h.tooltip(h.commit_status_lbl(status[0][1].status if status else 'not_reviewed'))}"> | |
196 | <div class="${'flag_status %s' % (status[0][1].status if status else 'not_reviewed')} pull-left reviewer_member_status"></div> |
|
196 | <div class="${'flag_status %s' % (status[0][1].status if status else 'not_reviewed')} pull-left reviewer_member_status"></div> | |
197 | </div> |
|
197 | </div> | |
198 |
< |
|
198 | <div id="reviewer_${member.user_id}_name" class="reviewer_name"> | |
199 | ${self.gravatar_with_user(member.email, 16)} |
|
199 | ${self.gravatar_with_user(member.email, 16)} <div class="reviewer">(${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div> | |
200 | (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</span> |
|
200 | </div> | |
201 | <input id="reviewer_${member.user_id}_input" type="hidden" value="${member.user_id}" name="review_members" /> |
|
201 | <input id="reviewer_${member.user_id}_input" type="hidden" value="${member.user_id}" name="review_members" /> | |
202 | %if c.allowed_to_update: |
|
202 | %if c.allowed_to_update: | |
203 | <div class="reviewer_member_remove action_button" onclick="removeReviewMember(${member.user_id}, true)" style="visibility: hidden;"> |
|
203 | <div class="reviewer_member_remove action_button" onclick="removeReviewMember(${member.user_id}, true)" style="visibility: hidden;"> |
@@ -73,6 +73,7 b' requirements = [' | |||||
73 | 'colander', |
|
73 | 'colander', | |
74 | 'decorator', |
|
74 | 'decorator', | |
75 | 'docutils', |
|
75 | 'docutils', | |
|
76 | 'gunicorn', | |||
76 | 'infrae.cache', |
|
77 | 'infrae.cache', | |
77 | 'ipython', |
|
78 | 'ipython', | |
78 | 'iso8601', |
|
79 | 'iso8601', | |
@@ -114,6 +115,7 b' test_requirements = [' | |||||
114 | 'lxml', |
|
115 | 'lxml', | |
115 | 'mock', |
|
116 | 'mock', | |
116 | 'pytest', |
|
117 | 'pytest', | |
|
118 | 'pytest-cov', | |||
117 | 'pytest-runner', |
|
119 | 'pytest-runner', | |
118 | ] |
|
120 | ] | |
119 |
|
121 |
General Comments 0
You need to be logged in to leave comments.
Login now