##// END OF EJS Templates
static: change static path to serve rhodecode static assets from...
marcink -
r522:3662eb25 default
parent child Browse files
Show More
@@ -1,33 +1,33 b''
1 Apache Reverse Proxy
1 Apache Reverse Proxy
2 ^^^^^^^^^^^^^^^^^^^^
2 ^^^^^^^^^^^^^^^^^^^^
3
3
4 Here is a sample configuration file for using Apache as a reverse proxy.
4 Here is a sample configuration file for using Apache as a reverse proxy.
5
5
6 .. code-block:: apache
6 .. code-block:: apache
7
7
8 <VirtualHost *:80>
8 <VirtualHost *:80>
9 ServerName hg.myserver.com
9 ServerName hg.myserver.com
10 ServerAlias hg.myserver.com
10 ServerAlias hg.myserver.com
11
11
12 ## uncomment to serve static files by Apache
12 ## uncomment to serve static files by Apache
13 ## ProxyPass /_static !
13 ## ProxyPass /_static/rhodecode !
14 ## Alias /_static /path/to/.rccontrol/enterprise-1/static
14 ## Alias /_static/rhodecode /path/to/.rccontrol/enterprise-1/static
15
15
16 <Proxy *>
16 <Proxy *>
17 Order allow,deny
17 Order allow,deny
18 Allow from all
18 Allow from all
19 </Proxy>
19 </Proxy>
20
20
21 ## Important !
21 ## Important !
22 ## Directive to properly generate url (clone url) for pylons
22 ## Directive to properly generate url (clone url) for pylons
23 ProxyPreserveHost On
23 ProxyPreserveHost On
24
24
25 ## RhodeCode instance running
25 ## RhodeCode instance running
26 ProxyPass / http://127.0.0.1:10002/
26 ProxyPass / http://127.0.0.1:10002/
27 ProxyPassReverse / http://127.0.0.1:10002/
27 ProxyPassReverse / http://127.0.0.1:10002/
28
28
29 ## to enable https use line below
29 ## to enable https use line below
30 #SetEnvIf X-Url-Scheme https HTTPS=1
30 #SetEnvIf X-Url-Scheme https HTTPS=1
31
31
32 </VirtualHost>
32 </VirtualHost>
33
33
@@ -1,92 +1,92 b''
1 Nginx Configuration Example
1 Nginx Configuration Example
2 ---------------------------
2 ---------------------------
3
3
4 Use the following example to configure Nginx as a your web server.
4 Use the following example to configure Nginx as a your web server.
5
5
6 .. code-block:: nginx
6 .. code-block:: nginx
7
7
8 upstream rc {
8 upstream rc {
9
9
10 server 127.0.0.1:10002;
10 server 127.0.0.1:10002;
11
11
12 # add more instances for load balancing
12 # add more instances for load balancing
13 # server 127.0.0.1:10003;
13 # server 127.0.0.1:10003;
14 # server 127.0.0.1:10004;
14 # server 127.0.0.1:10004;
15 }
15 }
16
16
17 ## gist alias
17 ## gist alias
18
18
19 server {
19 server {
20 listen 443;
20 listen 443;
21 server_name gist.myserver.com;
21 server_name gist.myserver.com;
22 access_log /var/log/nginx/gist.access.log;
22 access_log /var/log/nginx/gist.access.log;
23 error_log /var/log/nginx/gist.error.log;
23 error_log /var/log/nginx/gist.error.log;
24
24
25 ssl on;
25 ssl on;
26 ssl_certificate gist.rhodecode.myserver.com.crt;
26 ssl_certificate gist.rhodecode.myserver.com.crt;
27 ssl_certificate_key gist.rhodecode.myserver.com.key;
27 ssl_certificate_key gist.rhodecode.myserver.com.key;
28
28
29 ssl_session_timeout 5m;
29 ssl_session_timeout 5m;
30
30
31 ssl_protocols SSLv3 TLSv1;
31 ssl_protocols SSLv3 TLSv1;
32 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
32 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
33 ssl_prefer_server_ciphers on;
33 ssl_prefer_server_ciphers on;
34 add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
34 add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
35
35
36 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
36 # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
37 ssl_dhparam /etc/nginx/ssl/dhparam.pem;
37 ssl_dhparam /etc/nginx/ssl/dhparam.pem;
38
38
39 rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1;
39 rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1;
40 rewrite (.*) https://rhodecode.myserver.com/_admin/gists;
40 rewrite (.*) https://rhodecode.myserver.com/_admin/gists;
41 }
41 }
42
42
43 server {
43 server {
44 listen 443;
44 listen 443;
45 server_name rhodecode.myserver.com;
45 server_name rhodecode.myserver.com;
46 access_log /var/log/nginx/rhodecode.access.log;
46 access_log /var/log/nginx/rhodecode.access.log;
47 error_log /var/log/nginx/rhodecode.error.log;
47 error_log /var/log/nginx/rhodecode.error.log;
48
48
49 ssl on;
49 ssl on;
50 ssl_certificate rhodecode.myserver.com.crt;
50 ssl_certificate rhodecode.myserver.com.crt;
51 ssl_certificate_key rhodecode.myserver.com.key;
51 ssl_certificate_key rhodecode.myserver.com.key;
52
52
53 ssl_session_timeout 5m;
53 ssl_session_timeout 5m;
54
54
55 ssl_protocols SSLv3 TLSv1;
55 ssl_protocols SSLv3 TLSv1;
56 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
56 ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
57 ssl_prefer_server_ciphers on;
57 ssl_prefer_server_ciphers on;
58
58
59 include /etc/nginx/proxy.conf;
59 include /etc/nginx/proxy.conf;
60
60
61 ## uncomment to serve static files by nginx
61 ## uncomment to serve static files by nginx
62 # location /_static {
62 # location /_static/rhodecode {
63 # alias /path/to/.rccontrol/enterprise-1/static;
63 # alias /path/to/.rccontrol/enterprise-1/static;
64 # }
64 # }
65
65
66 ## channel stream live components
66 ## channel stream live components
67 location /_channelstream {
67 location /_channelstream {
68 rewrite /_channelstream/(.*) /$1 break;
68 rewrite /_channelstream/(.*) /$1 break;
69 proxy_connect_timeout 10;
69 proxy_connect_timeout 10;
70 proxy_send_timeout 10m;
70 proxy_send_timeout 10m;
71 proxy_read_timeout 10m;
71 proxy_read_timeout 10m;
72 tcp_nodelay off;
72 tcp_nodelay off;
73 proxy_pass http://127.0.0.1:9800;
73 proxy_pass http://127.0.0.1:9800;
74 proxy_set_header Host $host;
74 proxy_set_header Host $host;
75 proxy_set_header X-Real-IP $remote_addr;
75 proxy_set_header X-Real-IP $remote_addr;
76 proxy_set_header X-Url-Scheme $scheme;
76 proxy_set_header X-Url-Scheme $scheme;
77 proxy_set_header X-Forwarded-Proto $scheme;
77 proxy_set_header X-Forwarded-Proto $scheme;
78 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
78 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
79 gzip off;
79 gzip off;
80 proxy_http_version 1.1;
80 proxy_http_version 1.1;
81 proxy_set_header Upgrade $http_upgrade;
81 proxy_set_header Upgrade $http_upgrade;
82 proxy_set_header Connection "upgrade";
82 proxy_set_header Connection "upgrade";
83 }
83 }
84
84
85 location / {
85 location / {
86 try_files $uri @rhode;
86 try_files $uri @rhode;
87 }
87 }
88
88
89 location @rhode {
89 location @rhode {
90 proxy_pass http://rc;
90 proxy_pass http://rc;
91 }
91 }
92 }
92 }
@@ -1,395 +1,395 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Pylons middleware initialization
22 Pylons middleware initialization
23 """
23 """
24 import logging
24 import logging
25
25
26 from paste.registry import RegistryManager
26 from paste.registry import RegistryManager
27 from paste.gzipper import make_gzip_middleware
27 from paste.gzipper import make_gzip_middleware
28 from pylons.wsgiapp import PylonsApp
28 from pylons.wsgiapp import PylonsApp
29 from pyramid.authorization import ACLAuthorizationPolicy
29 from pyramid.authorization import ACLAuthorizationPolicy
30 from pyramid.config import Configurator
30 from pyramid.config import Configurator
31 from pyramid.static import static_view
31 from pyramid.static import static_view
32 from pyramid.settings import asbool, aslist
32 from pyramid.settings import asbool, aslist
33 from pyramid.wsgi import wsgiapp
33 from pyramid.wsgi import wsgiapp
34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
35 from pylons.controllers.util import abort, redirect
35 from pylons.controllers.util import abort, redirect
36 import pyramid.httpexceptions as httpexceptions
36 import pyramid.httpexceptions as httpexceptions
37 from pyramid.renderers import render_to_response, render
37 from pyramid.renderers import render_to_response, render
38 from routes.middleware import RoutesMiddleware
38 from routes.middleware import RoutesMiddleware
39 import routes.util
39 import routes.util
40
40
41 import rhodecode
41 import rhodecode
42 import rhodecode.integrations # do not remove this as it registers celery tasks
42 import rhodecode.integrations # do not remove this as it registers celery tasks
43 from rhodecode.config import patches
43 from rhodecode.config import patches
44 from rhodecode.config.routing import STATIC_FILE_PREFIX
44 from rhodecode.config.routing import STATIC_FILE_PREFIX
45 from rhodecode.config.environment import (
45 from rhodecode.config.environment import (
46 load_environment, load_pyramid_environment)
46 load_environment, load_pyramid_environment)
47 from rhodecode.lib.middleware import csrf
47 from rhodecode.lib.middleware import csrf
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
49 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
49 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
50 from rhodecode.lib.middleware.https_fixup import HttpsFixup
50 from rhodecode.lib.middleware.https_fixup import HttpsFixup
51 from rhodecode.lib.middleware.vcs import VCSMiddleware
51 from rhodecode.lib.middleware.vcs import VCSMiddleware
52 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
52 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
53
53
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 # this is used to avoid avoid the route lookup overhead in routesmiddleware
58 # this is used to avoid avoid the route lookup overhead in routesmiddleware
59 # for certain routes which won't go to pylons to - eg. static files, debugger
59 # for certain routes which won't go to pylons to - eg. static files, debugger
60 # it is only needed for the pylons migration and can be removed once complete
60 # it is only needed for the pylons migration and can be removed once complete
61 class SkippableRoutesMiddleware(RoutesMiddleware):
61 class SkippableRoutesMiddleware(RoutesMiddleware):
62 """ Routes middleware that allows you to skip prefixes """
62 """ Routes middleware that allows you to skip prefixes """
63
63
64 def __init__(self, *args, **kw):
64 def __init__(self, *args, **kw):
65 self.skip_prefixes = kw.pop('skip_prefixes', [])
65 self.skip_prefixes = kw.pop('skip_prefixes', [])
66 super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
66 super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
67
67
68 def __call__(self, environ, start_response):
68 def __call__(self, environ, start_response):
69 for prefix in self.skip_prefixes:
69 for prefix in self.skip_prefixes:
70 if environ['PATH_INFO'].startswith(prefix):
70 if environ['PATH_INFO'].startswith(prefix):
71 return self.app(environ, start_response)
71 return self.app(environ, start_response)
72
72
73 return super(SkippableRoutesMiddleware, self).__call__(
73 return super(SkippableRoutesMiddleware, self).__call__(
74 environ, start_response)
74 environ, start_response)
75
75
76
76
77 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
77 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
78 """Create a Pylons WSGI application and return it
78 """Create a Pylons WSGI application and return it
79
79
80 ``global_conf``
80 ``global_conf``
81 The inherited configuration for this application. Normally from
81 The inherited configuration for this application. Normally from
82 the [DEFAULT] section of the Paste ini file.
82 the [DEFAULT] section of the Paste ini file.
83
83
84 ``full_stack``
84 ``full_stack``
85 Whether or not this application provides a full WSGI stack (by
85 Whether or not this application provides a full WSGI stack (by
86 default, meaning it handles its own exceptions and errors).
86 default, meaning it handles its own exceptions and errors).
87 Disable full_stack when this application is "managed" by
87 Disable full_stack when this application is "managed" by
88 another WSGI middleware.
88 another WSGI middleware.
89
89
90 ``app_conf``
90 ``app_conf``
91 The application's local configuration. Normally specified in
91 The application's local configuration. Normally specified in
92 the [app:<name>] section of the Paste ini file (where <name>
92 the [app:<name>] section of the Paste ini file (where <name>
93 defaults to main).
93 defaults to main).
94
94
95 """
95 """
96 # Apply compatibility patches
96 # Apply compatibility patches
97 patches.kombu_1_5_1_python_2_7_11()
97 patches.kombu_1_5_1_python_2_7_11()
98 patches.inspect_getargspec()
98 patches.inspect_getargspec()
99
99
100 # Configure the Pylons environment
100 # Configure the Pylons environment
101 config = load_environment(global_conf, app_conf)
101 config = load_environment(global_conf, app_conf)
102
102
103 # The Pylons WSGI app
103 # The Pylons WSGI app
104 app = PylonsApp(config=config)
104 app = PylonsApp(config=config)
105 if rhodecode.is_test:
105 if rhodecode.is_test:
106 app = csrf.CSRFDetector(app)
106 app = csrf.CSRFDetector(app)
107
107
108 expected_origin = config.get('expected_origin')
108 expected_origin = config.get('expected_origin')
109 if expected_origin:
109 if expected_origin:
110 # The API can be accessed from other Origins.
110 # The API can be accessed from other Origins.
111 app = csrf.OriginChecker(app, expected_origin,
111 app = csrf.OriginChecker(app, expected_origin,
112 skip_urls=[routes.util.url_for('api')])
112 skip_urls=[routes.util.url_for('api')])
113
113
114
114
115 if asbool(full_stack):
115 if asbool(full_stack):
116
116
117 # Appenlight monitoring and error handler
117 # Appenlight monitoring and error handler
118 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
118 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
119
119
120 # we want our low level middleware to get to the request ASAP. We don't
120 # we want our low level middleware to get to the request ASAP. We don't
121 # need any pylons stack middleware in them
121 # need any pylons stack middleware in them
122 app = VCSMiddleware(app, config, appenlight_client)
122 app = VCSMiddleware(app, config, appenlight_client)
123
123
124 # Establish the Registry for this application
124 # Establish the Registry for this application
125 app = RegistryManager(app)
125 app = RegistryManager(app)
126
126
127 app.config = config
127 app.config = config
128
128
129 return app
129 return app
130
130
131
131
132 def make_pyramid_app(global_config, **settings):
132 def make_pyramid_app(global_config, **settings):
133 """
133 """
134 Constructs the WSGI application based on Pyramid and wraps the Pylons based
134 Constructs the WSGI application based on Pyramid and wraps the Pylons based
135 application.
135 application.
136
136
137 Specials:
137 Specials:
138
138
139 * We migrate from Pylons to Pyramid. While doing this, we keep both
139 * We migrate from Pylons to Pyramid. While doing this, we keep both
140 frameworks functional. This involves moving some WSGI middlewares around
140 frameworks functional. This involves moving some WSGI middlewares around
141 and providing access to some data internals, so that the old code is
141 and providing access to some data internals, so that the old code is
142 still functional.
142 still functional.
143
143
144 * The application can also be integrated like a plugin via the call to
144 * The application can also be integrated like a plugin via the call to
145 `includeme`. This is accompanied with the other utility functions which
145 `includeme`. This is accompanied with the other utility functions which
146 are called. Changing this should be done with great care to not break
146 are called. Changing this should be done with great care to not break
147 cases when these fragments are assembled from another place.
147 cases when these fragments are assembled from another place.
148
148
149 """
149 """
150 # The edition string should be available in pylons too, so we add it here
150 # The edition string should be available in pylons too, so we add it here
151 # before copying the settings.
151 # before copying the settings.
152 settings.setdefault('rhodecode.edition', 'Community Edition')
152 settings.setdefault('rhodecode.edition', 'Community Edition')
153
153
154 # As long as our Pylons application does expect "unprepared" settings, make
154 # As long as our Pylons application does expect "unprepared" settings, make
155 # sure that we keep an unmodified copy. This avoids unintentional change of
155 # sure that we keep an unmodified copy. This avoids unintentional change of
156 # behavior in the old application.
156 # behavior in the old application.
157 settings_pylons = settings.copy()
157 settings_pylons = settings.copy()
158
158
159 sanitize_settings_and_apply_defaults(settings)
159 sanitize_settings_and_apply_defaults(settings)
160 config = Configurator(settings=settings)
160 config = Configurator(settings=settings)
161 add_pylons_compat_data(config.registry, global_config, settings_pylons)
161 add_pylons_compat_data(config.registry, global_config, settings_pylons)
162
162
163 load_pyramid_environment(global_config, settings)
163 load_pyramid_environment(global_config, settings)
164
164
165 includeme_first(config)
165 includeme_first(config)
166 includeme(config)
166 includeme(config)
167 pyramid_app = config.make_wsgi_app()
167 pyramid_app = config.make_wsgi_app()
168 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
168 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
169 return pyramid_app
169 return pyramid_app
170
170
171
171
172 def add_pylons_compat_data(registry, global_config, settings):
172 def add_pylons_compat_data(registry, global_config, settings):
173 """
173 """
174 Attach data to the registry to support the Pylons integration.
174 Attach data to the registry to support the Pylons integration.
175 """
175 """
176 registry._pylons_compat_global_config = global_config
176 registry._pylons_compat_global_config = global_config
177 registry._pylons_compat_settings = settings
177 registry._pylons_compat_settings = settings
178
178
179
179
180 def webob_to_pyramid_http_response(webob_response):
180 def webob_to_pyramid_http_response(webob_response):
181 ResponseClass = httpexceptions.status_map[webob_response.status_int]
181 ResponseClass = httpexceptions.status_map[webob_response.status_int]
182 pyramid_response = ResponseClass(webob_response.status)
182 pyramid_response = ResponseClass(webob_response.status)
183 pyramid_response.status = webob_response.status
183 pyramid_response.status = webob_response.status
184 pyramid_response.headers.update(webob_response.headers)
184 pyramid_response.headers.update(webob_response.headers)
185 if pyramid_response.headers['content-type'] == 'text/html':
185 if pyramid_response.headers['content-type'] == 'text/html':
186 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
186 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
187 return pyramid_response
187 return pyramid_response
188
188
189
189
190 def error_handler(exception, request):
190 def error_handler(exception, request):
191 # TODO: dan: replace the old pylons error controller with this
191 # TODO: dan: replace the old pylons error controller with this
192 from rhodecode.model.settings import SettingsModel
192 from rhodecode.model.settings import SettingsModel
193 from rhodecode.lib.utils2 import AttributeDict
193 from rhodecode.lib.utils2 import AttributeDict
194
194
195 try:
195 try:
196 rc_config = SettingsModel().get_all_settings()
196 rc_config = SettingsModel().get_all_settings()
197 except Exception:
197 except Exception:
198 log.exception('failed to fetch settings')
198 log.exception('failed to fetch settings')
199 rc_config = {}
199 rc_config = {}
200
200
201 base_response = HTTPInternalServerError()
201 base_response = HTTPInternalServerError()
202 # prefer original exception for the response since it may have headers set
202 # prefer original exception for the response since it may have headers set
203 if isinstance(exception, HTTPError):
203 if isinstance(exception, HTTPError):
204 base_response = exception
204 base_response = exception
205
205
206 c = AttributeDict()
206 c = AttributeDict()
207 c.error_message = base_response.status
207 c.error_message = base_response.status
208 c.error_explanation = base_response.explanation or str(base_response)
208 c.error_explanation = base_response.explanation or str(base_response)
209 c.visual = AttributeDict()
209 c.visual = AttributeDict()
210
210
211 c.visual.rhodecode_support_url = (
211 c.visual.rhodecode_support_url = (
212 request.registry.settings.get('rhodecode_support_url') or
212 request.registry.settings.get('rhodecode_support_url') or
213 request.route_url('rhodecode_support')
213 request.route_url('rhodecode_support')
214 )
214 )
215 c.redirect_time = 0
215 c.redirect_time = 0
216 c.rhodecode_name = rc_config.get('rhodecode_title', '')
216 c.rhodecode_name = rc_config.get('rhodecode_title', '')
217 if not c.rhodecode_name:
217 if not c.rhodecode_name:
218 c.rhodecode_name = 'Rhodecode'
218 c.rhodecode_name = 'Rhodecode'
219
219
220 response = render_to_response(
220 response = render_to_response(
221 '/errors/error_document.html', {'c': c}, request=request,
221 '/errors/error_document.html', {'c': c}, request=request,
222 response=base_response)
222 response=base_response)
223
223
224 return response
224 return response
225
225
226
226
227 def includeme(config):
227 def includeme(config):
228 settings = config.registry.settings
228 settings = config.registry.settings
229
229
230 # plugin information
230 # plugin information
231 config.registry.rhodecode_plugins = {}
231 config.registry.rhodecode_plugins = {}
232
232
233 config.add_directive(
233 config.add_directive(
234 'register_rhodecode_plugin', register_rhodecode_plugin)
234 'register_rhodecode_plugin', register_rhodecode_plugin)
235
235
236 if asbool(settings.get('appenlight', 'false')):
236 if asbool(settings.get('appenlight', 'false')):
237 config.include('appenlight_client.ext.pyramid_tween')
237 config.include('appenlight_client.ext.pyramid_tween')
238
238
239 # Includes which are required. The application would fail without them.
239 # Includes which are required. The application would fail without them.
240 config.include('pyramid_mako')
240 config.include('pyramid_mako')
241 config.include('pyramid_beaker')
241 config.include('pyramid_beaker')
242 config.include('rhodecode.admin')
242 config.include('rhodecode.admin')
243 config.include('rhodecode.authentication')
243 config.include('rhodecode.authentication')
244 config.include('rhodecode.integrations')
244 config.include('rhodecode.integrations')
245 config.include('rhodecode.login')
245 config.include('rhodecode.login')
246 config.include('rhodecode.tweens')
246 config.include('rhodecode.tweens')
247 config.include('rhodecode.api')
247 config.include('rhodecode.api')
248 config.add_route(
248 config.add_route(
249 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
249 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
250
250
251 # Set the authorization policy.
251 # Set the authorization policy.
252 authz_policy = ACLAuthorizationPolicy()
252 authz_policy = ACLAuthorizationPolicy()
253 config.set_authorization_policy(authz_policy)
253 config.set_authorization_policy(authz_policy)
254
254
255 # Set the default renderer for HTML templates to mako.
255 # Set the default renderer for HTML templates to mako.
256 config.add_mako_renderer('.html')
256 config.add_mako_renderer('.html')
257
257
258 # include RhodeCode plugins
258 # include RhodeCode plugins
259 includes = aslist(settings.get('rhodecode.includes', []))
259 includes = aslist(settings.get('rhodecode.includes', []))
260 for inc in includes:
260 for inc in includes:
261 config.include(inc)
261 config.include(inc)
262
262
263 pylons_app = make_app(
263 pylons_app = make_app(
264 config.registry._pylons_compat_global_config,
264 config.registry._pylons_compat_global_config,
265 **config.registry._pylons_compat_settings)
265 **config.registry._pylons_compat_settings)
266 config.registry._pylons_compat_config = pylons_app.config
266 config.registry._pylons_compat_config = pylons_app.config
267
267
268 pylons_app_as_view = wsgiapp(pylons_app)
268 pylons_app_as_view = wsgiapp(pylons_app)
269
269
270 # Protect from VCS Server error related pages when server is not available
270 # Protect from VCS Server error related pages when server is not available
271 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
271 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
272 if not vcs_server_enabled:
272 if not vcs_server_enabled:
273 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
273 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
274
274
275
275
276 def pylons_app_with_error_handler(context, request):
276 def pylons_app_with_error_handler(context, request):
277 """
277 """
278 Handle exceptions from rc pylons app:
278 Handle exceptions from rc pylons app:
279
279
280 - old webob type exceptions get converted to pyramid exceptions
280 - old webob type exceptions get converted to pyramid exceptions
281 - pyramid exceptions are passed to the error handler view
281 - pyramid exceptions are passed to the error handler view
282 """
282 """
283 try:
283 try:
284 response = pylons_app_as_view(context, request)
284 response = pylons_app_as_view(context, request)
285 if 400 <= response.status_int <= 599: # webob type error responses
285 if 400 <= response.status_int <= 599: # webob type error responses
286 return error_handler(
286 return error_handler(
287 webob_to_pyramid_http_response(response), request)
287 webob_to_pyramid_http_response(response), request)
288 except HTTPError as e: # pyramid type exceptions
288 except HTTPError as e: # pyramid type exceptions
289 return error_handler(e, request)
289 return error_handler(e, request)
290 except Exception:
290 except Exception:
291 if settings.get('debugtoolbar.enabled', False):
291 if settings.get('debugtoolbar.enabled', False):
292 raise
292 raise
293 return error_handler(HTTPInternalServerError(), request)
293 return error_handler(HTTPInternalServerError(), request)
294 return response
294 return response
295
295
296 # This is the glue which allows us to migrate in chunks. By registering the
296 # This is the glue which allows us to migrate in chunks. By registering the
297 # pylons based application as the "Not Found" view in Pyramid, we will
297 # pylons based application as the "Not Found" view in Pyramid, we will
298 # fallback to the old application each time the new one does not yet know
298 # fallback to the old application each time the new one does not yet know
299 # how to handle a request.
299 # how to handle a request.
300 config.add_notfound_view(pylons_app_with_error_handler)
300 config.add_notfound_view(pylons_app_with_error_handler)
301
301
302 if not settings.get('debugtoolbar.enabled', False):
302 if not settings.get('debugtoolbar.enabled', False):
303 # if no toolbar, then any exception gets caught and rendered
303 # if no toolbar, then any exception gets caught and rendered
304 config.add_view(error_handler, context=Exception)
304 config.add_view(error_handler, context=Exception)
305
305
306 config.add_view(error_handler, context=HTTPError)
306 config.add_view(error_handler, context=HTTPError)
307
307
308
308
309 def includeme_first(config):
309 def includeme_first(config):
310 # redirect automatic browser favicon.ico requests to correct place
310 # redirect automatic browser favicon.ico requests to correct place
311 def favicon_redirect(context, request):
311 def favicon_redirect(context, request):
312 return redirect(
312 return redirect(
313 request.static_url('rhodecode:public/images/favicon.ico'))
313 request.static_url('rhodecode:public/images/favicon.ico'))
314
314
315 config.add_view(favicon_redirect, route_name='favicon')
315 config.add_view(favicon_redirect, route_name='favicon')
316 config.add_route('favicon', '/favicon.ico')
316 config.add_route('favicon', '/favicon.ico')
317
317
318 config.add_static_view(
318 config.add_static_view(
319 '_static/deform', 'deform:static')
319 '_static/deform', 'deform:static')
320 config.add_static_view(
320 config.add_static_view(
321 '_static', path='rhodecode:public', cache_max_age=3600 * 24)
321 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
322
322
323 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
323 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
324 """
324 """
325 Apply outer WSGI middlewares around the application.
325 Apply outer WSGI middlewares around the application.
326
326
327 Part of this has been moved up from the Pylons layer, so that the
327 Part of this has been moved up from the Pylons layer, so that the
328 data is also available if old Pylons code is hit through an already ported
328 data is also available if old Pylons code is hit through an already ported
329 view.
329 view.
330 """
330 """
331 settings = config.registry.settings
331 settings = config.registry.settings
332
332
333 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
333 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
334 pyramid_app = HttpsFixup(pyramid_app, settings)
334 pyramid_app = HttpsFixup(pyramid_app, settings)
335
335
336 # Add RoutesMiddleware to support the pylons compatibility tween during
336 # Add RoutesMiddleware to support the pylons compatibility tween during
337 # migration to pyramid.
337 # migration to pyramid.
338 pyramid_app = SkippableRoutesMiddleware(
338 pyramid_app = SkippableRoutesMiddleware(
339 pyramid_app, config.registry._pylons_compat_config['routes.map'],
339 pyramid_app, config.registry._pylons_compat_config['routes.map'],
340 skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
340 skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
341
341
342 if asbool(settings.get('appenlight', 'false')):
342 if asbool(settings.get('appenlight', 'false')):
343 pyramid_app, _ = wrap_in_appenlight_if_enabled(
343 pyramid_app, _ = wrap_in_appenlight_if_enabled(
344 pyramid_app, config.registry._pylons_compat_config)
344 pyramid_app, config.registry._pylons_compat_config)
345
345
346 if asbool(settings.get('gzip_responses', 'true')):
346 if asbool(settings.get('gzip_responses', 'true')):
347 pyramid_app = make_gzip_middleware(
347 pyramid_app = make_gzip_middleware(
348 pyramid_app, settings, compress_level=1)
348 pyramid_app, settings, compress_level=1)
349
349
350 return pyramid_app
350 return pyramid_app
351
351
352
352
353 def sanitize_settings_and_apply_defaults(settings):
353 def sanitize_settings_and_apply_defaults(settings):
354 """
354 """
355 Applies settings defaults and does all type conversion.
355 Applies settings defaults and does all type conversion.
356
356
357 We would move all settings parsing and preparation into this place, so that
357 We would move all settings parsing and preparation into this place, so that
358 we have only one place left which deals with this part. The remaining parts
358 we have only one place left which deals with this part. The remaining parts
359 of the application would start to rely fully on well prepared settings.
359 of the application would start to rely fully on well prepared settings.
360
360
361 This piece would later be split up per topic to avoid a big fat monster
361 This piece would later be split up per topic to avoid a big fat monster
362 function.
362 function.
363 """
363 """
364
364
365 # Pyramid's mako renderer has to search in the templates folder so that the
365 # Pyramid's mako renderer has to search in the templates folder so that the
366 # old templates still work. Ported and new templates are expected to use
366 # old templates still work. Ported and new templates are expected to use
367 # real asset specifications for the includes.
367 # real asset specifications for the includes.
368 mako_directories = settings.setdefault('mako.directories', [
368 mako_directories = settings.setdefault('mako.directories', [
369 # Base templates of the original Pylons application
369 # Base templates of the original Pylons application
370 'rhodecode:templates',
370 'rhodecode:templates',
371 ])
371 ])
372 log.debug(
372 log.debug(
373 "Using the following Mako template directories: %s",
373 "Using the following Mako template directories: %s",
374 mako_directories)
374 mako_directories)
375
375
376 # Default includes, possible to change as a user
376 # Default includes, possible to change as a user
377 pyramid_includes = settings.setdefault('pyramid.includes', [
377 pyramid_includes = settings.setdefault('pyramid.includes', [
378 'rhodecode.lib.middleware.request_wrapper',
378 'rhodecode.lib.middleware.request_wrapper',
379 ])
379 ])
380 log.debug(
380 log.debug(
381 "Using the following pyramid.includes: %s",
381 "Using the following pyramid.includes: %s",
382 pyramid_includes)
382 pyramid_includes)
383
383
384 # TODO: johbo: Re-think this, usually the call to config.include
384 # TODO: johbo: Re-think this, usually the call to config.include
385 # should allow to pass in a prefix.
385 # should allow to pass in a prefix.
386 settings.setdefault('rhodecode.api.url', '/_admin/api')
386 settings.setdefault('rhodecode.api.url', '/_admin/api')
387
387
388 _bool_setting(settings, 'vcs.server.enable', 'true')
388 _bool_setting(settings, 'vcs.server.enable', 'true')
389 _bool_setting(settings, 'is_test', 'false')
389 _bool_setting(settings, 'is_test', 'false')
390
390
391 return settings
391 return settings
392
392
393
393
394 def _bool_setting(settings, name, default):
394 def _bool_setting(settings, name, default):
395 settings[name] = asbool(settings.get(name, default))
395 settings[name] = asbool(settings.get(name, default))
@@ -1,235 +1,235 b''
1 // # Copyright (C) 2010-2016 RhodeCode GmbH
1 // # Copyright (C) 2010-2016 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 /**
19 /**
20 * Object holding the registered pyroutes.
20 * Object holding the registered pyroutes.
21 * Routes will be registered with the generated script
21 * Routes will be registered with the generated script
22 * rhodecode/public/js/rhodecode/base/pyroutes.js
22 * rhodecode/public/js/rhodecode/base/pyroutes.js
23 */
23 */
24 var PROUTES_MAP = {};
24 var PROUTES_MAP = {};
25
25
26 /**
26 /**
27 * PyRoutesJS
27 * PyRoutesJS
28 *
28 *
29 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
29 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
30 */
30 */
31 var pyroutes = (function() {
31 var pyroutes = (function() {
32 // access global map defined in special file pyroutes
32 // access global map defined in special file pyroutes
33 var matchlist = PROUTES_MAP;
33 var matchlist = PROUTES_MAP;
34 var sprintf = (function() {
34 var sprintf = (function() {
35 function get_type(variable) {
35 function get_type(variable) {
36 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
36 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
37 }
37 }
38 function str_repeat(input, multiplier) {
38 function str_repeat(input, multiplier) {
39 for (var output = []; multiplier > 0; output[--multiplier] = input) {
39 for (var output = []; multiplier > 0; output[--multiplier] = input) {
40 /* do nothing */
40 /* do nothing */
41 }
41 }
42 return output.join('');
42 return output.join('');
43 }
43 }
44 var str_format = function() {
44 var str_format = function() {
45 if (!str_format.cache.hasOwnProperty(arguments[0])) {
45 if (!str_format.cache.hasOwnProperty(arguments[0])) {
46 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
46 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
47 }
47 }
48 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
48 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
49 };
49 };
50
50
51 str_format.format = function(parse_tree, argv) {
51 str_format.format = function(parse_tree, argv) {
52 var cursor = 1,
52 var cursor = 1,
53 tree_length = parse_tree.length,
53 tree_length = parse_tree.length,
54 node_type = '',
54 node_type = '',
55 arg,
55 arg,
56 output = [],
56 output = [],
57 i, k,
57 i, k,
58 match,
58 match,
59 pad,
59 pad,
60 pad_character,
60 pad_character,
61 pad_length;
61 pad_length;
62 for (i = 0; i < tree_length; i++) {
62 for (i = 0; i < tree_length; i++) {
63 node_type = get_type(parse_tree[i]);
63 node_type = get_type(parse_tree[i]);
64 if (node_type === 'string') {
64 if (node_type === 'string') {
65 output.push(parse_tree[i]);
65 output.push(parse_tree[i]);
66 }
66 }
67 else if (node_type === 'array') {
67 else if (node_type === 'array') {
68 match = parse_tree[i]; // convenience purposes only
68 match = parse_tree[i]; // convenience purposes only
69 if (match[2]) { // keyword argument
69 if (match[2]) { // keyword argument
70 arg = argv[cursor];
70 arg = argv[cursor];
71 for (k = 0; k < match[2].length; k++) {
71 for (k = 0; k < match[2].length; k++) {
72 if (!arg.hasOwnProperty(match[2][k])) {
72 if (!arg.hasOwnProperty(match[2][k])) {
73 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
73 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
74 }
74 }
75 arg = arg[match[2][k]];
75 arg = arg[match[2][k]];
76 }
76 }
77 }
77 }
78 else if (match[1]) { // positional argument (explicit)
78 else if (match[1]) { // positional argument (explicit)
79 arg = argv[match[1]];
79 arg = argv[match[1]];
80 }
80 }
81 else { // positional argument (implicit)
81 else { // positional argument (implicit)
82 arg = argv[cursor++];
82 arg = argv[cursor++];
83 }
83 }
84
84
85 if (/[^s]/.test(match[8]) && (get_type(arg) !== 'number')) {
85 if (/[^s]/.test(match[8]) && (get_type(arg) !== 'number')) {
86 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
86 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
87 }
87 }
88 switch (match[8]) {
88 switch (match[8]) {
89 case 'b': arg = arg.toString(2); break;
89 case 'b': arg = arg.toString(2); break;
90 case 'c': arg = String.fromCharCode(arg); break;
90 case 'c': arg = String.fromCharCode(arg); break;
91 case 'd': arg = parseInt(arg, 10); break;
91 case 'd': arg = parseInt(arg, 10); break;
92 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
92 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
93 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
93 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
94 case 'o': arg = arg.toString(8); break;
94 case 'o': arg = arg.toString(8); break;
95 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg);
95 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg);
96 break;
96 break;
97 case 'u': arg = Math.abs(arg); break;
97 case 'u': arg = Math.abs(arg); break;
98 case 'x': arg = arg.toString(16); break;
98 case 'x': arg = arg.toString(16); break;
99 case 'X': arg = arg.toString(16).toUpperCase(); break;
99 case 'X': arg = arg.toString(16).toUpperCase(); break;
100 }
100 }
101 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
101 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
102 pad_character =
102 pad_character =
103 match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' ';
103 match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' ';
104 pad_length = match[6] - String(arg).length;
104 pad_length = match[6] - String(arg).length;
105 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
105 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
106 output.push(match[5] ? arg + pad : pad + arg);
106 output.push(match[5] ? arg + pad : pad + arg);
107 }
107 }
108 }
108 }
109 return output.join('');
109 return output.join('');
110 };
110 };
111
111
112 str_format.cache = {};
112 str_format.cache = {};
113
113
114 str_format.parse = function(fmt) {
114 str_format.parse = function(fmt) {
115 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
115 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
116 while (_fmt) {
116 while (_fmt) {
117 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
117 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
118 parse_tree.push(match[0]);
118 parse_tree.push(match[0]);
119 }
119 }
120 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
120 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
121 parse_tree.push('%');
121 parse_tree.push('%');
122 }
122 }
123 else if (
123 else if (
124 (match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
124 (match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
125 if (match[2]) {
125 if (match[2]) {
126 arg_names |= 1;
126 arg_names |= 1;
127 var field_list = [], replacement_field = match[2], field_match = [];
127 var field_list = [], replacement_field = match[2], field_match = [];
128 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
128 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
129 field_list.push(field_match[1]);
129 field_list.push(field_match[1]);
130 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
130 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
131 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
131 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
132 field_list.push(field_match[1]);
132 field_list.push(field_match[1]);
133 }
133 }
134 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
134 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
135 field_list.push(field_match[1]);
135 field_list.push(field_match[1]);
136 }
136 }
137 else {
137 else {
138 throw('[sprintf] huh?');
138 throw('[sprintf] huh?');
139 }
139 }
140 }
140 }
141 }
141 }
142 else {
142 else {
143 throw('[sprintf] huh?');
143 throw('[sprintf] huh?');
144 }
144 }
145 match[2] = field_list;
145 match[2] = field_list;
146 }
146 }
147 else {
147 else {
148 arg_names |= 2;
148 arg_names |= 2;
149 }
149 }
150 if (arg_names === 3) {
150 if (arg_names === 3) {
151 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
151 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
152 }
152 }
153 parse_tree.push(match);
153 parse_tree.push(match);
154 }
154 }
155 else {
155 else {
156 throw('[sprintf] huh?');
156 throw('[sprintf] huh?');
157 }
157 }
158 _fmt = _fmt.substring(match[0].length);
158 _fmt = _fmt.substring(match[0].length);
159 }
159 }
160 return parse_tree;
160 return parse_tree;
161 };
161 };
162 return str_format;
162 return str_format;
163 })();
163 })();
164
164
165 var vsprintf = function(fmt, argv) {
165 var vsprintf = function(fmt, argv) {
166 argv.unshift(fmt);
166 argv.unshift(fmt);
167 return sprintf.apply(null, argv);
167 return sprintf.apply(null, argv);
168 };
168 };
169 return {
169 return {
170 'asset': function(path, ver) {
170 'asset': function(path, ver) {
171 var asset_url = ASSET_URL || '/_static/';
171 var asset_url = ASSET_URL || '/_static/rhodecode/';
172 var ret = asset_url + path;
172 var ret = asset_url + path;
173 if (ver !== undefined) {
173 if (ver !== undefined) {
174 ret += '?ver=' + ver;
174 ret += '?ver=' + ver;
175 }
175 }
176 return ret;
176 return ret;
177 },
177 },
178 'url': function(route_name, params) {
178 'url': function(route_name, params) {
179 var result = route_name;
179 var result = route_name;
180 if (typeof(params) !== 'object'){
180 if (typeof(params) !== 'object'){
181 params = {};
181 params = {};
182 }
182 }
183 if (matchlist.hasOwnProperty(route_name)) {
183 if (matchlist.hasOwnProperty(route_name)) {
184 var route = matchlist[route_name];
184 var route = matchlist[route_name];
185 // param substitution
185 // param substitution
186 for(var i=0; i < route[1].length; i++) {
186 for(var i=0; i < route[1].length; i++) {
187 var param_name = route[1][i];
187 var param_name = route[1][i];
188 if (!params.hasOwnProperty(param_name))
188 if (!params.hasOwnProperty(param_name))
189 throw new Error(
189 throw new Error(
190 'parameter '+
190 'parameter '+
191 param_name +
191 param_name +
192 ' is missing in route"' +
192 ' is missing in route"' +
193 route_name + '" generation');
193 route_name + '" generation');
194 }
194 }
195 result = sprintf(route[0], params);
195 result = sprintf(route[0], params);
196
196
197 var ret = [];
197 var ret = [];
198 // extra params => GET
198 // extra params => GET
199 for (var param in params){
199 for (var param in params){
200 if (route[1].indexOf(param) === -1){
200 if (route[1].indexOf(param) === -1){
201 ret.push(encodeURIComponent(param) + "=" +
201 ret.push(encodeURIComponent(param) + "=" +
202 encodeURIComponent(params[param]));
202 encodeURIComponent(params[param]));
203 }
203 }
204 }
204 }
205 var _parts = ret.join("&");
205 var _parts = ret.join("&");
206 if(_parts){
206 if(_parts){
207 result = result +'?'+ _parts;
207 result = result +'?'+ _parts;
208 }
208 }
209 if(APPLICATION_URL) {
209 if(APPLICATION_URL) {
210 result = APPLICATION_URL + result;
210 result = APPLICATION_URL + result;
211 }
211 }
212 }
212 }
213
213
214 return result;
214 return result;
215 },
215 },
216 'register': function(route_name, route_tmpl, req_params) {
216 'register': function(route_name, route_tmpl, req_params) {
217 if (typeof(req_params) !== 'object') {
217 if (typeof(req_params) !== 'object') {
218 req_params = [];
218 req_params = [];
219 }
219 }
220 // fix escape
220 // fix escape
221 route_tmpl = unescape(route_tmpl);
221 route_tmpl = unescape(route_tmpl);
222 keys = [];
222 keys = [];
223 for(var i=0; i < req_params.length; i++) {
223 for(var i=0; i < req_params.length; i++) {
224 keys.push(req_params[i]);
224 keys.push(req_params[i]);
225 }
225 }
226 matchlist[route_name] = [
226 matchlist[route_name] = [
227 route_tmpl,
227 route_tmpl,
228 keys
228 keys
229 ];
229 ];
230 },
230 },
231 '_routes': function(){
231 '_routes': function(){
232 return matchlist;
232 return matchlist;
233 }
233 }
234 };
234 };
235 })();
235 })();
@@ -1,545 +1,545 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/debug_style/index.html"/>
2 <%inherit file="/debug_style/index.html"/>
3
3
4 <%def name="breadcrumbs_links()">
4 <%def name="breadcrumbs_links()">
5 ${h.link_to(_('Style'), h.url('debug_style_home'))}
5 ${h.link_to(_('Style'), h.url('debug_style_home'))}
6 &raquo;
6 &raquo;
7 ${c.active}
7 ${c.active}
8 </%def>
8 </%def>
9
9
10
10
11 <%def name="real_main()">
11 <%def name="real_main()">
12 <div class="box">
12 <div class="box">
13 <div class="title">
13 <div class="title">
14 ${self.breadcrumbs()}
14 ${self.breadcrumbs()}
15 </div>
15 </div>
16
16
17 <div class='sidebar-col-wrapper'>
17 <div class='sidebar-col-wrapper'>
18 ##main
18 ##main
19 ${self.sidebar()}
19 ${self.sidebar()}
20
20
21 <div class="main-content">
21 <div class="main-content">
22
22
23 <div style="opacity:.5">
23 <div style="opacity:.5">
24
24
25 <h2>Simple tables</h2>
25 <h2>Simple tables</h2>
26
26
27 <p>These styles will be adjusted later to provide a baseline style
27 <p>These styles will be adjusted later to provide a baseline style
28 for all tables without classes added, whether part of the
28 for all tables without classes added, whether part of the
29 application or not. Currently, some of the
29 application or not. Currently, some of the
30 application-specific styles are applied to this table.</p>
30 application-specific styles are applied to this table.</p>
31 <p>This is a baseline style for all tables, whether part of the
31 <p>This is a baseline style for all tables, whether part of the
32 application or not. It has no class applied for styling. Use
32 application or not. It has no class applied for styling. Use
33 the "rctable" class as outlined before for tables which are
33 the "rctable" class as outlined before for tables which are
34 part of the RhodeCode application.</p>
34 part of the RhodeCode application.</p>
35 <table>
35 <table>
36 <tbody>
36 <tbody>
37 <tr>
37 <tr>
38 <th>Header A</th>
38 <th>Header A</th>
39 <th>Header B</th>
39 <th>Header B</th>
40 <th>Header C</th>
40 <th>Header C</th>
41 <th>Header D</th>
41 <th>Header D</th>
42 </tr>
42 </tr>
43 <tr>
43 <tr>
44 <td>Content of col A</td>
44 <td>Content of col A</td>
45 <td>Content of col B</td>
45 <td>Content of col B</td>
46 <td>Content of col C</td>
46 <td>Content of col C</td>
47 <td>Content of col D</td>
47 <td>Content of col D</td>
48 </tr>
48 </tr>
49 <tr>
49 <tr>
50 <td>Content of col A</td>
50 <td>Content of col A</td>
51 <td>Content of col B</td>
51 <td>Content of col B</td>
52 <td>Content of col C</td>
52 <td>Content of col C</td>
53 <td>Content of col D</td>
53 <td>Content of col D</td>
54 </tr>
54 </tr>
55 <tr>
55 <tr>
56 <td>Content of col A</td>
56 <td>Content of col A</td>
57 <td>Content of col B</td>
57 <td>Content of col B</td>
58 <td>Content of col C</td>
58 <td>Content of col C</td>
59 <td>Content of col D</td>
59 <td>Content of col D</td>
60 </tr>
60 </tr>
61 <tr>
61 <tr>
62 <td>Content of col A</td>
62 <td>Content of col A</td>
63 <td>Content of col B</td>
63 <td>Content of col B</td>
64 <td>Content of col C</td>
64 <td>Content of col C</td>
65 <td>Content of col D</td>
65 <td>Content of col D</td>
66 </tr>
66 </tr>
67 </tbody>
67 </tbody>
68 </table>
68 </table>
69 </div>
69 </div>
70
70
71
71
72
72
73
73
74 <h2>RC application table with examples</h2>
74 <h2>RC application table with examples</h2>
75
75
76 <p>This is a standard table which applies the rhodecode-specific styling to be used
76 <p>This is a standard table which applies the rhodecode-specific styling to be used
77 throughout the application; it has <code>&lt;table class="rctable"&gt;</code>.
77 throughout the application; it has <code>&lt;table class="rctable"&gt;</code>.
78 <br/>
78 <br/>
79 By default, table data is not truncated, and wraps inside of the <code>&lt;td&gt
79 By default, table data is not truncated, and wraps inside of the <code>&lt;td&gt
80 ;</code>. To prevent wrapping and contain data on one line, use the <code>&lt;
80 ;</code>. To prevent wrapping and contain data on one line, use the <code>&lt;
81 class="truncate-wrap"&gt;</code> on the <code>&lt;td&gt;</code>, and <code>span
81 class="truncate-wrap"&gt;</code> on the <code>&lt;td&gt;</code>, and <code>span
82 class="truncate"</code> around the specific data to be truncated.
82 class="truncate"</code> around the specific data to be truncated.
83 </p>
83 </p>
84 <p>
84 <p>
85 Ellipsis is added via CSS. Please always add a row of headers using <code>&lt;th
85 Ellipsis is added via CSS. Please always add a row of headers using <code>&lt;th
86 &gt;</code> to the top of a table.
86 &gt;</code> to the top of a table.
87 </p>
87 </p>
88
88
89 ## TODO: johbo: in case we have more tables with examples, we should
89 ## TODO: johbo: in case we have more tables with examples, we should
90 ## create a generic class here.
90 ## create a generic class here.
91 <table class="rctable issuetracker">
91 <table class="rctable issuetracker">
92 <thead>
92 <thead>
93 <tr>
93 <tr>
94 <th>Header A</th>
94 <th>Header A</th>
95 <th>Header B</th>
95 <th>Header B</th>
96 <th>Header C</th>
96 <th>Header C</th>
97 <th>Header D</th>
97 <th>Header D</th>
98 </tr>
98 </tr>
99 </thead>
99 </thead>
100 <tbody>
100 <tbody>
101 <tr>
101 <tr>
102 <td class="issue-tracker-example">
102 <td class="issue-tracker-example">
103 Example of col A
103 Example of col A
104 </td>
104 </td>
105 <td class="issue-tracker-example">
105 <td class="issue-tracker-example">
106 Example of col B
106 Example of col B
107 </td>
107 </td>
108 <td class="issue-tracker-example">
108 <td class="issue-tracker-example">
109 Example of col C
109 Example of col C
110 </td>
110 </td>
111 <td class="issue-tracker-example">
111 <td class="issue-tracker-example">
112 Example of col D
112 Example of col D
113 </td>
113 </td>
114 </tr>
114 </tr>
115 <tr>
115 <tr>
116 <td>Content of col A</td>
116 <td>Content of col A</td>
117 <td>Content of col B</td>
117 <td>Content of col B</td>
118 <td>Content of col C which is very long and will not be
118 <td>Content of col C which is very long and will not be
119 truncated because sometimes people just want to write
119 truncated because sometimes people just want to write
120 really, really long commit messages which explain what
120 really, really long commit messages which explain what
121 they did in excruciating detail and you really, really
121 they did in excruciating detail and you really, really
122 want to read them.</td>
122 want to read them.</td>
123 <td>Content of col D</td>
123 <td>Content of col D</td>
124 </tr>
124 </tr>
125 <tr>
125 <tr>
126 <td>Content of col A</td>
126 <td>Content of col A</td>
127 <td>Content of col B</td>
127 <td>Content of col B</td>
128 <td>Content of col C</td>
128 <td>Content of col C</td>
129 <td class="truncate-wrap"><span class="truncate">Truncated
129 <td class="truncate-wrap"><span class="truncate">Truncated
130 content of column D truncate truncate truncatetruncate
130 content of column D truncate truncate truncatetruncate
131 truncate truncate</span></td>
131 truncate truncate</span></td>
132 </tr>
132 </tr>
133 </tbody>
133 </tbody>
134 </table>
134 </table>
135
135
136 <h2>RC application table data classes</h2>
136 <h2>RC application table data classes</h2>
137
137
138 <p>The following tables contain documentation of all existing table data classes.
138 <p>The following tables contain documentation of all existing table data classes.
139 Please update when new classes are made.
139 Please update when new classes are made.
140 </p>
140 </p>
141 <table class="rctable examples">
141 <table class="rctable examples">
142 <thead>
142 <thead>
143 <tr>
143 <tr>
144 <th>Class</th>
144 <th>Class</th>
145 <th>Description</th>
145 <th>Description</th>
146 <th>Example</th>
146 <th>Example</th>
147 </tr>
147 </tr>
148 </thead>
148 </thead>
149 <tbody>
149 <tbody>
150 <td>td-user</td>
150 <td>td-user</td>
151 <td>Any username/gravatar combination (see also Icons style).</td>
151 <td>Any username/gravatar combination (see also Icons style).</td>
152 <td class="td-user author">
152 <td class="td-user author">
153 <img class="gravatar" alt="gravatar" src="https://secure.gravatar.com/avatar/0c9a7e6674b6f0b35d98dbe073e3f0ab?d=identicon&amp;s=32" height="16" width="16">
153 <img class="gravatar" alt="gravatar" src="https://secure.gravatar.com/avatar/0c9a7e6674b6f0b35d98dbe073e3f0ab?d=identicon&amp;s=32" height="16" width="16">
154 <span title="Oliver Strobel <oliver@rhodecode.com>" class="user">ostrobel (Oliver Strobel)</span>
154 <span title="Oliver Strobel <oliver@rhodecode.com>" class="user">ostrobel (Oliver Strobel)</span>
155 </td>
155 </td>
156 </tr>
156 </tr>
157 <tr>
157 <tr>
158 <td>td-hash</td>
158 <td>td-hash</td>
159 <td>Any hash; a commit, revision, etc. Use <code>&lt;pre&gt;</code> and header 'Commit'</td>
159 <td>Any hash; a commit, revision, etc. Use <code>&lt;pre&gt;</code> and header 'Commit'</td>
160 <td class="td-commit">
160 <td class="td-commit">
161 <pre><a href="/anothercpythonforkkkk/files/8d6b27837c6979983b037693fe975cdbb761b500/">r93699:8d6b27837c69</a></pre>
161 <pre><a href="/anothercpythonforkkkk/files/8d6b27837c6979983b037693fe975cdbb761b500/">r93699:8d6b27837c69</a></pre>
162 </td>
162 </td>
163 </tr>
163 </tr>
164 <tr>
164 <tr>
165 <td>td-rss</td>
165 <td>td-rss</td>
166 <td>RSS feed link icon</td>
166 <td>RSS feed link icon</td>
167 <td class="td-rss">
167 <td class="td-rss">
168 <a title="Subscribe to rss feed" href="/feed/rss"><i class="icon-rss-sign"></i></a>
168 <a title="Subscribe to rss feed" href="/feed/rss"><i class="icon-rss-sign"></i></a>
169 </td>
169 </td>
170 </tr>
170 </tr>
171 <tr>
171 <tr>
172 <td>td-componentname</td>
172 <td>td-componentname</td>
173 <td>Any group, file, gist, or directory name.</td>
173 <td>Any group, file, gist, or directory name.</td>
174 <td class="td-componentname">
174 <td class="td-componentname">
175 <a href="/cpythonfork">
175 <a href="/cpythonfork">
176 <span title="Mercurial repository"><i class="icon-hg"></i></span>
176 <span title="Mercurial repository"><i class="icon-hg"></i></span>
177 <i class="icon-unlock-alt" title="Public repository"></i>
177 <i class="icon-unlock-alt" title="Public repository"></i>
178 rhodecode-dev-restyle-fork
178 rhodecode-dev-restyle-fork
179 </a>
179 </a>
180 </td>
180 </td>
181 </tr>
181 </tr>
182 <tr>
182 <tr>
183 <td>td-tags</td>
183 <td>td-tags</td>
184 <td>Any cell containing tags, including branches and bookmarks.</td>
184 <td>Any cell containing tags, including branches and bookmarks.</td>
185 <td class="td-tags">
185 <td class="td-tags">
186 <span class="branchtag tag" title="Branch default">
186 <span class="branchtag tag" title="Branch default">
187 <a href="/rhodecode-dev-restyle- fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
187 <a href="/rhodecode-dev-restyle- fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
188 </span>
188 </span>
189 </td>
189 </td>
190 </tr>
190 </tr>
191 <tr>
191 <tr>
192 <td>tags-truncate</td>
192 <td>tags-truncate</td>
193 <td>Used to truncate a cell containing tags; avoid if possible.</td>
193 <td>Used to truncate a cell containing tags; avoid if possible.</td>
194 <td class="td-tags truncate-wrap">
194 <td class="td-tags truncate-wrap">
195 <div class="truncate tags-truncate">
195 <div class="truncate tags-truncate">
196 <div class="autoexpand">
196 <div class="autoexpand">
197 <span class="tagtag tag" title="Tag tip">
197 <span class="tagtag tag" title="Tag tip">
198 <a href="/rhodecode-dev-restyle-fork/files/e519d5a0e71466d27257ddff921c4a13c540408e/"><i class="icon-tag"></i>tip</a>
198 <a href="/rhodecode-dev-restyle-fork/files/e519d5a0e71466d27257ddff921c4a13c540408e/"><i class="icon-tag"></i>tip</a>
199 </span>
199 </span>
200 <span class="branchtag tag" title="Branch default">
200 <span class="branchtag tag" title="Branch default">
201 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
201 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
202 </span>
202 </span>
203 <span class="branchtag tag" title="Branch default">
203 <span class="branchtag tag" title="Branch default">
204 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
204 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
205 </span>
205 </span>
206 </div>
206 </div>
207 </div>
207 </div>
208 </td>
208 </td>
209 </tr>
209 </tr>
210 <tr>
210 <tr>
211 <td>td-ip</td>
211 <td>td-ip</td>
212 <td>Any ip address.</td>
212 <td>Any ip address.</td>
213 <td class="td-ip">
213 <td class="td-ip">
214 172.16.115.168
214 172.16.115.168
215 </td>
215 </td>
216 </tr>
216 </tr>
217 <tr>
217 <tr>
218 <td>td-type</td>
218 <td>td-type</td>
219 <td>A state or an auth type.</td>
219 <td>A state or an auth type.</td>
220 <td class="td-type">
220 <td class="td-type">
221 rhodecode
221 rhodecode
222 </td>
222 </td>
223 </tr>
223 </tr>
224 <tr>
224 <tr>
225 <td>td-authtoken</td>
225 <td>td-authtoken</td>
226 <td>For auth tokens. Use truncate classes for hover expand; see html.</td>
226 <td>For auth tokens. Use truncate classes for hover expand; see html.</td>
227 <td class="truncate-wrap td-authtoken">
227 <td class="truncate-wrap td-authtoken">
228 <div class="truncate autoexpand">
228 <div class="truncate autoexpand">
229 <code>688df65b87d3ad16ae9f8fc6338a551d40f41c7a</code>
229 <code>688df65b87d3ad16ae9f8fc6338a551d40f41c7a</code>
230 </div>
230 </div>
231 </td>
231 </td>
232 </tr>
232 </tr>
233 <tr>
233 <tr>
234 <td>td-action</td>
234 <td>td-action</td>
235 <td>Buttons which perform an action.</td>
235 <td>Buttons which perform an action.</td>
236 <td class="td-action">
236 <td class="td-action">
237 <div class="grid_edit">
237 <div class="grid_edit">
238 <a href="/_admin/users/2/edit" title="edit">
238 <a href="/_admin/users/2/edit" title="edit">
239 <i class="icon-pencil"></i>Edit</a>
239 <i class="icon-pencil"></i>Edit</a>
240 </div>
240 </div>
241 <div class="grid_delete">
241 <div class="grid_delete">
242 <form action="/_admin/users/2" method="post">
242 <form action="/_admin/users/2" method="post">
243 <i class="icon-remove-sign"></i>
243 <i class="icon-remove-sign"></i>
244 <input class="btn btn-danger btn-link" id="remove_user_2" name="remove_" type="submit" value="delete">
244 <input class="btn btn-danger btn-link" id="remove_user_2" name="remove_" type="submit" value="delete">
245 </form>
245 </form>
246 </div>
246 </div>
247 </td>
247 </td>
248 </tr>
248 </tr>
249 <tr>
249 <tr>
250 <td>td-radio</td>
250 <td>td-radio</td>
251 <td>Radio buttons for a form. Centers element.</td>
251 <td>Radio buttons for a form. Centers element.</td>
252 <td class="td-radio">
252 <td class="td-radio">
253 <input type="radio" checked="checked" value="" name="1" id="read"></td>
253 <input type="radio" checked="checked" value="" name="1" id="read"></td>
254 </tr>
254 </tr>
255 <tr>
255 <tr>
256 <td>td-checkbox</td>
256 <td>td-checkbox</td>
257 <td>Checkbox for a form. Centers element.</td>
257 <td>Checkbox for a form. Centers element.</td>
258 <td class="td-checkbox">
258 <td class="td-checkbox">
259 <input type="checkbox" checked="checked" value="" name="1" id="read"></td>
259 <input type="checkbox" checked="checked" value="" name="1" id="read"></td>
260 </tr>
260 </tr>
261 <tr>
261 <tr>
262 <tr>
262 <tr>
263 <td>td-buttons</td>
263 <td>td-buttons</td>
264 <td>Buttons.</td>
264 <td>Buttons.</td>
265 <td class="td-buttons">
265 <td class="td-buttons">
266 <span class="btn btn-mini btn-primary">feed access</span>
266 <span class="btn btn-mini btn-primary">feed access</span>
267 </td>
267 </td>
268 </tr>
268 </tr>
269 <tr>
269 <tr>
270 <td>td-compare</td>
270 <td>td-compare</td>
271 <td>Radio buttons to compare commits.</td>
271 <td>Radio buttons to compare commits.</td>
272 <td class=" td-compare">
272 <td class=" td-compare">
273 <input class="compare-radio-button" type="radio" name="compare_source" value="2.0">
273 <input class="compare-radio-button" type="radio" name="compare_source" value="2.0">
274 <input class="compare-radio-button" type="radio" name="compare_target" value="2.0">
274 <input class="compare-radio-button" type="radio" name="compare_target" value="2.0">
275 </td>
275 </td>
276 </tr>
276 </tr>
277 <tr>
277 <tr>
278 <td>td-comments</td>
278 <td>td-comments</td>
279 <td>Comments indicator icon.</td>
279 <td>Comments indicator icon.</td>
280 <td>
280 <td>
281 <i class="icon-comment icon-comment-colored"></i> 0
281 <i class="icon-comment icon-comment-colored"></i> 0
282 </td>
282 </td>
283 </tr>
283 </tr>
284 <tr>
284 <tr>
285 <td>td-status</td>
285 <td>td-status</td>
286 <td>Status indicator icon.</td>
286 <td>Status indicator icon.</td>
287 <td class="td-description">
287 <td class="td-description">
288 <div class="flag_status under_review pull-left"></div>
288 <div class="flag_status under_review pull-left"></div>
289 </td>
289 </td>
290 </tr>
290 </tr>
291 </tbody>
291 </tbody>
292 </table>
292 </table>
293 <table class="dataTable rctable examples">
293 <table class="dataTable rctable examples">
294 <tbody>
294 <tbody>
295 <tr>
295 <tr>
296 <td>quick_repo_menu</td>
296 <td>quick_repo_menu</td>
297 <td>Hidden menu generated by dataTable.</td>
297 <td>Hidden menu generated by dataTable.</td>
298 <td class="quick_repo_menu">
298 <td class="quick_repo_menu">
299 <i class="pointer icon-more"></i>
299 <i class="pointer icon-more"></i>
300 <div class="menu_items_container" style="display: none;">
300 <div class="menu_items_container" style="display: none;">
301 <ul class="menu_items">
301 <ul class="menu_items">
302 <li>
302 <li>
303 <a title="Summary" href="/anothercpythonforkkkk-fork">
303 <a title="Summary" href="/anothercpythonforkkkk-fork">
304 <span>Summary</span>
304 <span>Summary</span>
305 </a>
305 </a>
306 </li>
306 </li>
307 <li>
307 <li>
308 <a title="Changelog" href="/anothercpythonforkkkk-fork/changelog">
308 <a title="Changelog" href="/anothercpythonforkkkk-fork/changelog">
309 <span>Changelog</span>
309 <span>Changelog</span>
310 </a>
310 </a>
311 </li>
311 </li>
312 <li>
312 <li>
313 <a title="Files" href="/anothercpythonforkkkk-fork/files/tip/">
313 <a title="Files" href="/anothercpythonforkkkk-fork/files/tip/">
314 <span>Files</span>
314 <span>Files</span>
315 </a>
315 </a>
316 </li>
316 </li>
317 <li>
317 <li>
318 <a title="Fork" href="/anothercpythonforkkkk-fork/fork">
318 <a title="Fork" href="/anothercpythonforkkkk-fork/fork">
319 <span>Fork</span>
319 <span>Fork</span>
320 </a>
320 </a>
321 </li>
321 </li>
322 </ul>
322 </ul>
323 </div>
323 </div>
324 </td>
324 </td>
325 <td></td>
325 <td></td>
326 </tr>
326 </tr>
327 </tbody>
327 </tbody>
328 </table>
328 </table>
329 <script>quick_repo_menu();</script>
329 <script>quick_repo_menu();</script>
330 <table class="rctable examples">
330 <table class="rctable examples">
331 <tbody>
331 <tbody>
332 <tr>
332 <tr>
333 <td>td-description</td>
333 <td>td-description</td>
334 <td>Any description. They may be rather long, and using the expand_commit outlined below is recommended.</td>
334 <td>Any description. They may be rather long, and using the expand_commit outlined below is recommended.</td>
335 <td class="td-description">
335 <td class="td-description">
336 Ultrices mattis! Enim pellentesque lacus, sit magna natoque risus turpis ut, auctor ultrices facilisis dapibus odio? Parturient! Porta egestas nascetur, quis, elementum dolor, in magna ac dis sit etiam turpis, scelerisque! Integer tristique aliquam.
336 Ultrices mattis! Enim pellentesque lacus, sit magna natoque risus turpis ut, auctor ultrices facilisis dapibus odio? Parturient! Porta egestas nascetur, quis, elementum dolor, in magna ac dis sit etiam turpis, scelerisque! Integer tristique aliquam.
337 </td>
337 </td>
338 </tr>
338 </tr>
339 </tbody>
339 </tbody>
340 </table>
340 </table>
341 <table id="changesets" class="rctable examples end">
341 <table id="changesets" class="rctable examples end">
342 <tbody>
342 <tbody>
343 <tr>
343 <tr>
344 <td>expand_commit</td>
344 <td>expand_commit</td>
345 <td>Expands a long message; see html+js.</td>
345 <td>Expands a long message; see html+js.</td>
346 <td class="expand_commit" data-commit-id="2ffc6faabc7a9c790b1b452943a3f0c047b8b436" title="Expand commit message">
346 <td class="expand_commit" data-commit-id="2ffc6faabc7a9c790b1b452943a3f0c047b8b436" title="Expand commit message">
347 <div class="show_more_col">
347 <div class="show_more_col">
348 <i class="show_more"></i>
348 <i class="show_more"></i>
349 </div>
349 </div>
350 </td>
350 </td>
351 <td class="mid td-description">
351 <td class="mid td-description">
352 <div class="log-container truncate-wrap">
352 <div class="log-container truncate-wrap">
353 <div id="c-2ffc6faabc7a9c790b1b452943a3f0c047b8b436" class="message truncate" data-message-raw="tests: Test echo method on the server object
353 <div id="c-2ffc6faabc7a9c790b1b452943a3f0c047b8b436" class="message truncate" data-message-raw="tests: Test echo method on the server object
354
354
355 This only works for Pyro4 so far, have to extend it still for HTTP to work.">tests: Test echo method on the server object
355 This only works for Pyro4 so far, have to extend it still for HTTP to work.">tests: Test echo method on the server object
356
356
357 This only works for Pyro4 so far, have to extend it still for HTTP to work.</div>
357 This only works for Pyro4 so far, have to extend it still for HTTP to work.</div>
358 </div>
358 </div>
359 </td>
359 </td>
360 </tr>
360 </tr>
361 </tbody>
361 </tbody>
362 </table>
362 </table>
363 <script type="text/javascript">
363 <script type="text/javascript">
364 var cache = {}
364 var cache = {}
365 $('.expand_commit').on('click',function(e){
365 $('.expand_commit').on('click',function(e){
366 var target_expand = $(this);
366 var target_expand = $(this);
367 var cid = target_expand.data('commitId');
367 var cid = target_expand.data('commitId');
368
368
369 if (target_expand.hasClass('open')){
369 if (target_expand.hasClass('open')){
370 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
370 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
371 $('#t-'+cid).css({'height': '1.5em', 'max-height': '1.5em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
371 $('#t-'+cid).css({'height': '1.5em', 'max-height': '1.5em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
372 target_expand.removeClass('open');
372 target_expand.removeClass('open');
373 }
373 }
374 else {
374 else {
375 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
375 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
376 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
376 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
377 target_expand.addClass('open');
377 target_expand.addClass('open');
378 }
378 }
379 });
379 });
380
380
381 </script>
381 </script>
382 <p>The following classes currently do not have unique styles applied.</p>
382 <p>The following classes currently do not have unique styles applied.</p>
383 <table class="rctable examples end">
383 <table class="rctable examples end">
384 <tbody>
384 <tbody>
385 <tr>
385 <tr>
386 <td>td-regex</td>
386 <td>td-regex</td>
387 <td>Regex patterns</td>
387 <td>Regex patterns</td>
388 <td class="td-regex">(?:#)(?P<issue_id>\d+)</td>
388 <td class="td-regex">(?:#)(?P<issue_id>\d+)</td>
389 </tr>
389 </tr>
390 <tr>
390 <tr>
391 <td>td-url</td>
391 <td>td-url</td>
392 <td>Any URL.</td>
392 <td>Any URL.</td>
393 <td class="td-url">https://rhodecode.com</td>
393 <td class="td-url">https://rhodecode.com</td>
394 </tr>
394 </tr>
395 <tr>
395 <tr>
396 <td>td-journalaction</td>
396 <td>td-journalaction</td>
397 <td>Action listed in a journal</td>
397 <td>Action listed in a journal</td>
398 <td class="td-journalaction">started following repository supervisor-fork-4</td>
398 <td class="td-journalaction">started following repository supervisor-fork-4</td>
399 </tr>
399 </tr>
400 <tr>
400 <tr>
401 <td>td-iprange</td>
401 <td>td-iprange</td>
402 <td>Any ip address.</td>
402 <td>Any ip address.</td>
403 <td class="td-ip">127.0.0.1-127.0.0.10</td>
403 <td class="td-ip">127.0.0.1-127.0.0.10</td>
404 </tr>
404 </tr>
405 <tr>
405 <tr>
406 <td>td-exp</td>
406 <td>td-exp</td>
407 <td>Expiration time.</td>
407 <td>Expiration time.</td>
408 <td class="td-exp">never</td>
408 <td class="td-exp">never</td>
409 </tr>
409 </tr>
410 <tr>
410 <tr>
411 <td>td-prefix</td>
411 <td>td-prefix</td>
412 <td>Prefixes outlined in settings.</td>
412 <td>Prefixes outlined in settings.</td>
413 <td class="td-prefix">ubuntu-92539</td>
413 <td class="td-prefix">ubuntu-92539</td>
414 </tr>
414 </tr>
415 <tr>
415 <tr>
416 <td>td-cachekey</td>
416 <td>td-cachekey</td>
417 <td>Cache key value.</td>
417 <td>Cache key value.</td>
418 <td class="td-cachekey">ubuntu-92539supervisor</td>
418 <td class="td-cachekey">ubuntu-92539supervisor</td>
419 </tr>
419 </tr>
420 <tr>
420 <tr>
421 <td>td-email</td>
421 <td>td-email</td>
422 <td>Any email address.</td>
422 <td>Any email address.</td>
423 <td class="td-email">example@rhodecode.com</td>
423 <td class="td-email">example@rhodecode.com</td>
424 </tr>
424 </tr>
425 <tr>
425 <tr>
426 <td>td-active</td>
426 <td>td-active</td>
427 <td>Shows active state with icon-true/icon-false.</td>
427 <td>Shows active state with icon-true/icon-false.</td>
428 <td class="td-active"><i class="icon-false"></i></td>
428 <td class="td-active"><i class="icon-false"></i></td>
429 </tr>
429 </tr>
430 <tr>
430 <tr>
431 <td>td-size</td>
431 <td>td-size</td>
432 <td>File, repo, or directory size.</td>
432 <td>File, repo, or directory size.</td>
433 <td class="td-size">89 MB</td>
433 <td class="td-size">89 MB</td>
434 </tr>
434 </tr>
435 <tr>
435 <tr>
436 <td>td-number</td>
436 <td>td-number</td>
437 <td>Any numerical data.</td>
437 <td>Any numerical data.</td>
438 <td class="td-number">42</td>
438 <td class="td-number">42</td>
439 </tr>
439 </tr>
440 <tr>
440 <tr>
441 <td>td-message</td>
441 <td>td-message</td>
442 <td>Any commit message. Often treated with the truncate class used for descriptions as well.</td>
442 <td>Any commit message. Often treated with the truncate class used for descriptions as well.</td>
443 <td class="td-message">Updated the files</td>
443 <td class="td-message">Updated the files</td>
444 </tr>
444 </tr>
445 </tbody>
445 </tbody>
446 </table>
446 </table>
447
447
448
448
449 <h2>Permissions table</h2>
449 <h2>Permissions table</h2>
450
450
451 <p>
451 <p>
452 This is a special-case table; it has
452 This is a special-case table; it has
453 <code>table class="rctable permissions"</code>
453 <code>table class="rctable permissions"</code>
454 where "rctable" applies the rhodecode styling as above, and
454 where "rctable" applies the rhodecode styling as above, and
455 "permissions" adds an extra layer of customization specific to
455 "permissions" adds an extra layer of customization specific to
456 permissions tables. Other special-case tables may exist or be
456 permissions tables. Other special-case tables may exist or be
457 created if necessary.
457 created if necessary.
458 </p>
458 </p>
459
459
460 <table class="rctable permissions">
460 <table class="rctable permissions">
461 <tr>
461 <tr>
462 <th class="td-radio">none</th>
462 <th class="td-radio">none</th>
463 <th class="td-radio">read</th>
463 <th class="td-radio">read</th>
464 <th class="td-radio">write</th>
464 <th class="td-radio">write</th>
465 <th class="td-radio">admin</th>
465 <th class="td-radio">admin</th>
466 <th>user/user group</th>
466 <th>user/user group</th>
467 <th></th>
467 <th></th>
468 </tr>
468 </tr>
469 <tr class="perm_admin_row">
469 <tr class="perm_admin_row">
470 <td class="td-radio"><input type="radio" value="repository.none"
470 <td class="td-radio"><input type="radio" value="repository.none"
471 name="admin_perm_2" id="admin_perm_2_repositorynone"
471 name="admin_perm_2" id="admin_perm_2_repositorynone"
472 disabled="disabled"></td>
472 disabled="disabled"></td>
473 <td class="td-radio"><input type="radio" value="repository.read"
473 <td class="td-radio"><input type="radio" value="repository.read"
474 name="admin_perm_2" id="admin_perm_2_repositoryread"
474 name="admin_perm_2" id="admin_perm_2_repositoryread"
475 disabled="disabled"></td>
475 disabled="disabled"></td>
476 <td class="td-radio"><input type="radio" value="repository.write"
476 <td class="td-radio"><input type="radio" value="repository.write"
477 name="admin_perm_2" id="admin_perm_2_repositorywrite"
477 name="admin_perm_2" id="admin_perm_2_repositorywrite"
478 disabled="disabled"></td>
478 disabled="disabled"></td>
479 <td class="td-radio"><input type="radio" value="repository.admin"
479 <td class="td-radio"><input type="radio" value="repository.admin"
480 name="admin_perm_2" id="admin_perm_2_repositoryadmin"
480 name="admin_perm_2" id="admin_perm_2_repositoryadmin"
481 disabled="disabled" checked="checked"></td>
481 disabled="disabled" checked="checked"></td>
482 <td>
482 <td>
483 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
483 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
484 <span class="user">dev (super admin) (owner)</span>
484 <span class="user">dev (super admin) (owner)</span>
485 </td>
485 </td>
486 <td></td>
486 <td></td>
487 </tr>
487 </tr>
488 <tr>
488 <tr>
489 <td colspan="4">
489 <td colspan="4">
490 <span class="private_repo_msg">
490 <span class="private_repo_msg">
491 private repository
491 private repository
492 </span>
492 </span>
493 </td>
493 </td>
494 <td class="private_repo_msg">
494 <td class="private_repo_msg">
495 <i class="icon-user"></i>
495 <i class="icon-user"></i>
496 default - only people explicitly added here will have access</td>
496 default - only people explicitly added here will have access</td>
497 <td></td>
497 <td></td>
498 </tr>
498 </tr>
499 <tr>
499 <tr>
500 <td class="td-radio"><input type="radio" value="repository.none"
500 <td class="td-radio"><input type="radio" value="repository.none"
501 name="u_perm_1" id="u_perm_1_repositorynone"></td>
501 name="u_perm_1" id="u_perm_1_repositorynone"></td>
502 <td class="td-radio"><input type="radio" checked="checked"
502 <td class="td-radio"><input type="radio" checked="checked"
503 value="repository.read" name="u_perm_1"
503 value="repository.read" name="u_perm_1"
504 id="u_perm_1_repositoryread"></td>
504 id="u_perm_1_repositoryread"></td>
505 <td class="td-radio"><input type="radio" value="repository.write"
505 <td class="td-radio"><input type="radio" value="repository.write"
506 name="u_perm_1" id="u_perm_1_repositorywrite"></td>
506 name="u_perm_1" id="u_perm_1_repositorywrite"></td>
507 <td class="td-radio"><input type="radio" value="repository.admin"
507 <td class="td-radio"><input type="radio" value="repository.admin"
508 name="u_perm_1" id="u_perm_1_repositoryadmin"></td>
508 name="u_perm_1" id="u_perm_1_repositoryadmin"></td>
509 <td>
509 <td>
510 <img class="gravatar" src="/_static/images/user30.png" height="16" width="16">
510 <img class="gravatar" src="/_static/rhodecode/images/user30.png" height="16" width="16">
511 <span class="user">default</span>
511 <span class="user">default</span>
512 </td>
512 </td>
513 <td></td>
513 <td></td>
514 </tr>
514 </tr>
515 <tr>
515 <tr>
516 <td class="td-radio"><input type="radio" value="repository.none"
516 <td class="td-radio"><input type="radio" value="repository.none"
517 name="u_perm_2" id="u_perm_2_repositorynone"></td>
517 name="u_perm_2" id="u_perm_2_repositorynone"></td>
518 <td class="td-radio"><input type="radio" checked="checked"
518 <td class="td-radio"><input type="radio" checked="checked"
519 value="repository.read" name="u_perm_2"
519 value="repository.read" name="u_perm_2"
520 id="u_perm_2_repositoryread"></td>
520 id="u_perm_2_repositoryread"></td>
521 <td class="td-radio"><input type="radio" value="repository.write"
521 <td class="td-radio"><input type="radio" value="repository.write"
522 name="u_perm_2" id="u_perm_2_repositorywrite"></td>
522 name="u_perm_2" id="u_perm_2_repositorywrite"></td>
523 <td class="td-radio"><input type="radio" value="repository.admin"
523 <td class="td-radio"><input type="radio" value="repository.admin"
524 name="u_perm_2" id="u_perm_2_repositoryadmin"></td>
524 name="u_perm_2" id="u_perm_2_repositoryadmin"></td>
525 <td>
525 <td>
526 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
526 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
527 <a class="user" href="/_admin/users/2/edit">dev</a>
527 <a class="user" href="/_admin/users/2/edit">dev</a>
528 </td>
528 </td>
529 <td>
529 <td>
530 <span member_type="user" member="2"
530 <span member_type="user" member="2"
531 class="btn action_button btn-link btn-danger">revoke</span>
531 class="btn action_button btn-link btn-danger">revoke</span>
532 </td>
532 </td>
533 </tr>
533 </tr>
534 </tbody>
534 </tbody>
535 </table>
535 </table>
536 <div class="link" id="add_perm">
536 <div class="link" id="add_perm">
537 Add new
537 Add new
538 </div>
538 </div>
539
539
540
540
541
541
542 </div>
542 </div>
543 </div>
543 </div>
544 </div>
544 </div>
545 </%def>
545 </%def>
General Comments 0
You need to be logged in to leave comments. Login now