##// END OF EJS Templates
assets: convert pylons static files to pyramid static_url, fixes #3504
dan -
r454:a3b0830f default
parent child Browse files
Show More
@@ -1,612 +1,612 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode Enterprise - configuration file #
3 # RhodeCode Enterprise - configuration file #
4 # Built-in functions and variables #
4 # Built-in functions and variables #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 # #
6 # #
7 ################################################################################
7 ################################################################################
8
8
9 [DEFAULT]
9 [DEFAULT]
10 debug = true
10 debug = true
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the email address which should receive ##
12 ## Uncomment and replace with the email address which should receive ##
13 ## any error reports after an application crash ##
13 ## any error reports after an application crash ##
14 ## Additionally these settings will be used by the RhodeCode mailing system ##
14 ## Additionally these settings will be used by the RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20 #email_prefix = [RhodeCode]
20 #email_prefix = [RhodeCode]
21
21
22 #smtp_server = mail.server.com
22 #smtp_server = mail.server.com
23 #smtp_username =
23 #smtp_username =
24 #smtp_password =
24 #smtp_password =
25 #smtp_port =
25 #smtp_port =
26 #smtp_use_tls = false
26 #smtp_use_tls = false
27 #smtp_use_ssl = true
27 #smtp_use_ssl = true
28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 #smtp_auth =
29 #smtp_auth =
30
30
31 [server:main]
31 [server:main]
32 ## COMMON ##
32 ## COMMON ##
33 host = 127.0.0.1
33 host = 127.0.0.1
34 port = 5000
34 port = 5000
35
35
36 ##################################
36 ##################################
37 ## WAITRESS WSGI SERVER ##
37 ## WAITRESS WSGI SERVER ##
38 ## Recommended for Development ##
38 ## Recommended for Development ##
39 ##################################
39 ##################################
40 use = egg:waitress#main
40 use = egg:waitress#main
41 ## number of worker threads
41 ## number of worker threads
42 threads = 5
42 threads = 5
43 ## MAX BODY SIZE 100GB
43 ## MAX BODY SIZE 100GB
44 max_request_body_size = 107374182400
44 max_request_body_size = 107374182400
45 ## Use poll instead of select, fixes file descriptors limits problems.
45 ## Use poll instead of select, fixes file descriptors limits problems.
46 ## May not work on old windows systems.
46 ## May not work on old windows systems.
47 asyncore_use_poll = true
47 asyncore_use_poll = true
48
48
49
49
50 ##########################
50 ##########################
51 ## GUNICORN WSGI SERVER ##
51 ## GUNICORN WSGI SERVER ##
52 ##########################
52 ##########################
53 ## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
53 ## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
54 #use = egg:gunicorn#main
54 #use = egg:gunicorn#main
55 ## Sets the number of process workers. You must set `instance_id = *`
55 ## Sets the number of process workers. You must set `instance_id = *`
56 ## when this option is set to more than one worker, recommended
56 ## when this option is set to more than one worker, recommended
57 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
57 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
58 ## The `instance_id = *` must be set in the [app:main] section below
58 ## The `instance_id = *` must be set in the [app:main] section below
59 #workers = 2
59 #workers = 2
60 ## number of threads for each of the worker, must be set to 1 for gevent
60 ## number of threads for each of the worker, must be set to 1 for gevent
61 ## generally recommened to be at 1
61 ## generally recommened to be at 1
62 #threads = 1
62 #threads = 1
63 ## process name
63 ## process name
64 #proc_name = rhodecode
64 #proc_name = rhodecode
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
68 ## The maximum number of simultaneous clients. Valid only for Gevent
69 #worker_connections = 10
69 #worker_connections = 10
70 ## max number of requests that worker will handle before being gracefully
70 ## max number of requests that worker will handle before being gracefully
71 ## restarted, could prevent memory leaks
71 ## restarted, could prevent memory leaks
72 #max_requests = 1000
72 #max_requests = 1000
73 #max_requests_jitter = 30
73 #max_requests_jitter = 30
74 ## amount of time a worker can spend with handling a request before it
74 ## amount of time a worker can spend with handling a request before it
75 ## gets killed and restarted. Set to 6hrs
75 ## gets killed and restarted. Set to 6hrs
76 #timeout = 21600
76 #timeout = 21600
77
77
78
78
79 ## prefix middleware for RhodeCode, disables force_https flag.
79 ## prefix middleware for RhodeCode, disables force_https flag.
80 ## allows to set RhodeCode under a prefix in server.
80 ## allows to set RhodeCode under a prefix in server.
81 ## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
81 ## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
82 #[filter:proxy-prefix]
82 #[filter:proxy-prefix]
83 #use = egg:PasteDeploy#prefix
83 #use = egg:PasteDeploy#prefix
84 #prefix = /<your-prefix>
84 #prefix = /<your-prefix>
85
85
86 [app:main]
86 [app:main]
87 use = egg:rhodecode-enterprise-ce
87 use = egg:rhodecode-enterprise-ce
88 ## enable proxy prefix middleware, defined below
88 ## enable proxy prefix middleware, defined below
89 #filter-with = proxy-prefix
89 #filter-with = proxy-prefix
90
90
91 # During development the we want to have the debug toolbar enabled
91 # During development the we want to have the debug toolbar enabled
92 pyramid.includes =
92 pyramid.includes =
93 pyramid_debugtoolbar
93 pyramid_debugtoolbar
94 rhodecode.utils.debugtoolbar
94 rhodecode.utils.debugtoolbar
95 rhodecode.lib.middleware.request_wrapper
95 rhodecode.lib.middleware.request_wrapper
96
96
97 pyramid.reload_templates = true
97 pyramid.reload_templates = true
98
98
99 debugtoolbar.hosts = 0.0.0.0/0
99 debugtoolbar.hosts = 0.0.0.0/0
100 debugtoolbar.exclude_prefixes =
100 debugtoolbar.exclude_prefixes =
101 /css
101 /css
102 /fonts
102 /fonts
103 /images
103 /images
104 /js
104 /js
105
105
106 ## RHODECODE PLUGINS ##
106 ## RHODECODE PLUGINS ##
107 rhodecode.includes =
107 rhodecode.includes =
108 rhodecode.api
108 rhodecode.api
109
109
110
110
111 # api prefix url
111 # api prefix url
112 rhodecode.api.url = /_admin/api
112 rhodecode.api.url = /_admin/api
113
113
114
114
115 ## END RHODECODE PLUGINS ##
115 ## END RHODECODE PLUGINS ##
116
116
117 ## encryption key used to encrypt social plugin tokens,
117 ## encryption key used to encrypt social plugin tokens,
118 ## remote_urls with credentials etc, if not set it defaults to
118 ## remote_urls with credentials etc, if not set it defaults to
119 ## `beaker.session.secret`
119 ## `beaker.session.secret`
120 #rhodecode.encrypted_values.secret =
120 #rhodecode.encrypted_values.secret =
121
121
122 ## decryption strict mode (enabled by default). It controls if decryption raises
122 ## decryption strict mode (enabled by default). It controls if decryption raises
123 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
123 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
124 #rhodecode.encrypted_values.strict = false
124 #rhodecode.encrypted_values.strict = false
125
125
126 full_stack = true
126 full_stack = true
127
127
128 ## Serve static files via RhodeCode, disable to serve them via HTTP server
128 ## Return gzipped responses
129 static_files = true
129 gzip_responses = true
130
130
131 # autogenerate javascript routes file on startup
131 # autogenerate javascript routes file on startup
132 generate_js_files = false
132 generate_js_files = false
133
133
134 ## Optional Languages
134 ## Optional Languages
135 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
135 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
136 lang = en
136 lang = en
137
137
138 ## perform a full repository scan on each server start, this should be
138 ## perform a full repository scan on each server start, this should be
139 ## set to false after first startup, to allow faster server restarts.
139 ## set to false after first startup, to allow faster server restarts.
140 startup.import_repos = false
140 startup.import_repos = false
141
141
142 ## Uncomment and set this path to use archive download cache.
142 ## Uncomment and set this path to use archive download cache.
143 ## Once enabled, generated archives will be cached at this location
143 ## Once enabled, generated archives will be cached at this location
144 ## and served from the cache during subsequent requests for the same archive of
144 ## and served from the cache during subsequent requests for the same archive of
145 ## the repository.
145 ## the repository.
146 #archive_cache_dir = /tmp/tarballcache
146 #archive_cache_dir = /tmp/tarballcache
147
147
148 ## change this to unique ID for security
148 ## change this to unique ID for security
149 app_instance_uuid = rc-production
149 app_instance_uuid = rc-production
150
150
151 ## cut off limit for large diffs (size in bytes)
151 ## cut off limit for large diffs (size in bytes)
152 cut_off_limit_diff = 1024000
152 cut_off_limit_diff = 1024000
153 cut_off_limit_file = 256000
153 cut_off_limit_file = 256000
154
154
155 ## use cache version of scm repo everywhere
155 ## use cache version of scm repo everywhere
156 vcs_full_cache = true
156 vcs_full_cache = true
157
157
158 ## force https in RhodeCode, fixes https redirects, assumes it's always https
158 ## force https in RhodeCode, fixes https redirects, assumes it's always https
159 ## Normally this is controlled by proper http flags sent from http server
159 ## Normally this is controlled by proper http flags sent from http server
160 force_https = false
160 force_https = false
161
161
162 ## use Strict-Transport-Security headers
162 ## use Strict-Transport-Security headers
163 use_htsts = false
163 use_htsts = false
164
164
165 ## number of commits stats will parse on each iteration
165 ## number of commits stats will parse on each iteration
166 commit_parse_limit = 25
166 commit_parse_limit = 25
167
167
168 ## git rev filter option, --all is the default filter, if you need to
168 ## git rev filter option, --all is the default filter, if you need to
169 ## hide all refs in changelog switch this to --branches --tags
169 ## hide all refs in changelog switch this to --branches --tags
170 git_rev_filter = --branches --tags
170 git_rev_filter = --branches --tags
171
171
172 # Set to true if your repos are exposed using the dumb protocol
172 # Set to true if your repos are exposed using the dumb protocol
173 git_update_server_info = false
173 git_update_server_info = false
174
174
175 ## RSS/ATOM feed options
175 ## RSS/ATOM feed options
176 rss_cut_off_limit = 256000
176 rss_cut_off_limit = 256000
177 rss_items_per_page = 10
177 rss_items_per_page = 10
178 rss_include_diff = false
178 rss_include_diff = false
179
179
180 ## gist URL alias, used to create nicer urls for gist. This should be an
180 ## gist URL alias, used to create nicer urls for gist. This should be an
181 ## url that does rewrites to _admin/gists/<gistid>.
181 ## url that does rewrites to _admin/gists/<gistid>.
182 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
182 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
183 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/<gistid>
183 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/<gistid>
184 gist_alias_url =
184 gist_alias_url =
185
185
186 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
186 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
187 ## used for access.
187 ## used for access.
188 ## Adding ?auth_token = <token> to the url authenticates this request as if it
188 ## Adding ?auth_token = <token> to the url authenticates this request as if it
189 ## came from the the logged in user who own this authentication token.
189 ## came from the the logged in user who own this authentication token.
190 ##
190 ##
191 ## Syntax is <ControllerClass>:<function_pattern>.
191 ## Syntax is <ControllerClass>:<function_pattern>.
192 ## To enable access to raw_files put `FilesController:raw`.
192 ## To enable access to raw_files put `FilesController:raw`.
193 ## To enable access to patches add `ChangesetController:changeset_patch`.
193 ## To enable access to patches add `ChangesetController:changeset_patch`.
194 ## The list should be "," separated and on a single line.
194 ## The list should be "," separated and on a single line.
195 ##
195 ##
196 ## Recommended controllers to enable:
196 ## Recommended controllers to enable:
197 # ChangesetController:changeset_patch,
197 # ChangesetController:changeset_patch,
198 # ChangesetController:changeset_raw,
198 # ChangesetController:changeset_raw,
199 # FilesController:raw,
199 # FilesController:raw,
200 # FilesController:archivefile,
200 # FilesController:archivefile,
201 # GistsController:*,
201 # GistsController:*,
202 api_access_controllers_whitelist =
202 api_access_controllers_whitelist =
203
203
204 ## default encoding used to convert from and to unicode
204 ## default encoding used to convert from and to unicode
205 ## can be also a comma separated list of encoding in case of mixed encodings
205 ## can be also a comma separated list of encoding in case of mixed encodings
206 default_encoding = UTF-8
206 default_encoding = UTF-8
207
207
208 ## instance-id prefix
208 ## instance-id prefix
209 ## a prefix key for this instance used for cache invalidation when running
209 ## a prefix key for this instance used for cache invalidation when running
210 ## multiple instances of rhodecode, make sure it's globally unique for
210 ## multiple instances of rhodecode, make sure it's globally unique for
211 ## all running rhodecode instances. Leave empty if you don't use it
211 ## all running rhodecode instances. Leave empty if you don't use it
212 instance_id =
212 instance_id =
213
213
214 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
214 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
215 ## of an authentication plugin also if it is disabled by it's settings.
215 ## of an authentication plugin also if it is disabled by it's settings.
216 ## This could be useful if you are unable to log in to the system due to broken
216 ## This could be useful if you are unable to log in to the system due to broken
217 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
217 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
218 ## module to log in again and fix the settings.
218 ## module to log in again and fix the settings.
219 ##
219 ##
220 ## Available builtin plugin IDs (hash is part of the ID):
220 ## Available builtin plugin IDs (hash is part of the ID):
221 ## egg:rhodecode-enterprise-ce#rhodecode
221 ## egg:rhodecode-enterprise-ce#rhodecode
222 ## egg:rhodecode-enterprise-ce#pam
222 ## egg:rhodecode-enterprise-ce#pam
223 ## egg:rhodecode-enterprise-ce#ldap
223 ## egg:rhodecode-enterprise-ce#ldap
224 ## egg:rhodecode-enterprise-ce#jasig_cas
224 ## egg:rhodecode-enterprise-ce#jasig_cas
225 ## egg:rhodecode-enterprise-ce#headers
225 ## egg:rhodecode-enterprise-ce#headers
226 ## egg:rhodecode-enterprise-ce#crowd
226 ## egg:rhodecode-enterprise-ce#crowd
227 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
227 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
228
228
229 ## alternative return HTTP header for failed authentication. Default HTTP
229 ## alternative return HTTP header for failed authentication. Default HTTP
230 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
230 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
231 ## handling that causing a series of failed authentication calls.
231 ## handling that causing a series of failed authentication calls.
232 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
232 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
233 ## This will be served instead of default 401 on bad authnetication
233 ## This will be served instead of default 401 on bad authnetication
234 auth_ret_code =
234 auth_ret_code =
235
235
236 ## use special detection method when serving auth_ret_code, instead of serving
236 ## use special detection method when serving auth_ret_code, instead of serving
237 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
237 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
238 ## and then serve auth_ret_code to clients
238 ## and then serve auth_ret_code to clients
239 auth_ret_code_detection = false
239 auth_ret_code_detection = false
240
240
241 ## locking return code. When repository is locked return this HTTP code. 2XX
241 ## locking return code. When repository is locked return this HTTP code. 2XX
242 ## codes don't break the transactions while 4XX codes do
242 ## codes don't break the transactions while 4XX codes do
243 lock_ret_code = 423
243 lock_ret_code = 423
244
244
245 ## allows to change the repository location in settings page
245 ## allows to change the repository location in settings page
246 allow_repo_location_change = true
246 allow_repo_location_change = true
247
247
248 ## allows to setup custom hooks in settings page
248 ## allows to setup custom hooks in settings page
249 allow_custom_hooks_settings = true
249 allow_custom_hooks_settings = true
250
250
251 ## generated license token, goto license page in RhodeCode settings to obtain
251 ## generated license token, goto license page in RhodeCode settings to obtain
252 ## new token
252 ## new token
253 license_token =
253 license_token =
254
254
255 ## supervisor connection uri, for managing supervisor and logs.
255 ## supervisor connection uri, for managing supervisor and logs.
256 supervisor.uri =
256 supervisor.uri =
257 ## supervisord group name/id we only want this RC instance to handle
257 ## supervisord group name/id we only want this RC instance to handle
258 supervisor.group_id = dev
258 supervisor.group_id = dev
259
259
260 ## Display extended labs settings
260 ## Display extended labs settings
261 labs_settings_active = true
261 labs_settings_active = true
262
262
263 ####################################
263 ####################################
264 ### CELERY CONFIG ####
264 ### CELERY CONFIG ####
265 ####################################
265 ####################################
266 use_celery = false
266 use_celery = false
267 broker.host = localhost
267 broker.host = localhost
268 broker.vhost = rabbitmqhost
268 broker.vhost = rabbitmqhost
269 broker.port = 5672
269 broker.port = 5672
270 broker.user = rabbitmq
270 broker.user = rabbitmq
271 broker.password = qweqwe
271 broker.password = qweqwe
272
272
273 celery.imports = rhodecode.lib.celerylib.tasks
273 celery.imports = rhodecode.lib.celerylib.tasks
274
274
275 celery.result.backend = amqp
275 celery.result.backend = amqp
276 celery.result.dburi = amqp://
276 celery.result.dburi = amqp://
277 celery.result.serialier = json
277 celery.result.serialier = json
278
278
279 #celery.send.task.error.emails = true
279 #celery.send.task.error.emails = true
280 #celery.amqp.task.result.expires = 18000
280 #celery.amqp.task.result.expires = 18000
281
281
282 celeryd.concurrency = 2
282 celeryd.concurrency = 2
283 #celeryd.log.file = celeryd.log
283 #celeryd.log.file = celeryd.log
284 celeryd.log.level = debug
284 celeryd.log.level = debug
285 celeryd.max.tasks.per.child = 1
285 celeryd.max.tasks.per.child = 1
286
286
287 ## tasks will never be sent to the queue, but executed locally instead.
287 ## tasks will never be sent to the queue, but executed locally instead.
288 celery.always.eager = false
288 celery.always.eager = false
289
289
290 ####################################
290 ####################################
291 ### BEAKER CACHE ####
291 ### BEAKER CACHE ####
292 ####################################
292 ####################################
293 # default cache dir for templates. Putting this into a ramdisk
293 # default cache dir for templates. Putting this into a ramdisk
294 ## can boost performance, eg. %(here)s/data_ramdisk
294 ## can boost performance, eg. %(here)s/data_ramdisk
295 cache_dir = %(here)s/data
295 cache_dir = %(here)s/data
296
296
297 ## locking and default file storage for Beaker. Putting this into a ramdisk
297 ## locking and default file storage for Beaker. Putting this into a ramdisk
298 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
298 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
299 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
299 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
300 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
300 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
301
301
302 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
302 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
303
303
304 beaker.cache.super_short_term.type = memory
304 beaker.cache.super_short_term.type = memory
305 beaker.cache.super_short_term.expire = 10
305 beaker.cache.super_short_term.expire = 10
306 beaker.cache.super_short_term.key_length = 256
306 beaker.cache.super_short_term.key_length = 256
307
307
308 beaker.cache.short_term.type = memory
308 beaker.cache.short_term.type = memory
309 beaker.cache.short_term.expire = 60
309 beaker.cache.short_term.expire = 60
310 beaker.cache.short_term.key_length = 256
310 beaker.cache.short_term.key_length = 256
311
311
312 beaker.cache.long_term.type = memory
312 beaker.cache.long_term.type = memory
313 beaker.cache.long_term.expire = 36000
313 beaker.cache.long_term.expire = 36000
314 beaker.cache.long_term.key_length = 256
314 beaker.cache.long_term.key_length = 256
315
315
316 beaker.cache.sql_cache_short.type = memory
316 beaker.cache.sql_cache_short.type = memory
317 beaker.cache.sql_cache_short.expire = 10
317 beaker.cache.sql_cache_short.expire = 10
318 beaker.cache.sql_cache_short.key_length = 256
318 beaker.cache.sql_cache_short.key_length = 256
319
319
320 # default is memory cache, configure only if required
320 # default is memory cache, configure only if required
321 # using multi-node or multi-worker setup
321 # using multi-node or multi-worker setup
322 #beaker.cache.auth_plugins.type = ext:database
322 #beaker.cache.auth_plugins.type = ext:database
323 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
323 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
324 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
324 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
325 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
325 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
326 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
326 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
327 #beaker.cache.auth_plugins.sa.pool_size = 10
327 #beaker.cache.auth_plugins.sa.pool_size = 10
328 #beaker.cache.auth_plugins.sa.max_overflow = 0
328 #beaker.cache.auth_plugins.sa.max_overflow = 0
329
329
330 beaker.cache.repo_cache_long.type = memorylru_base
330 beaker.cache.repo_cache_long.type = memorylru_base
331 beaker.cache.repo_cache_long.max_items = 4096
331 beaker.cache.repo_cache_long.max_items = 4096
332 beaker.cache.repo_cache_long.expire = 2592000
332 beaker.cache.repo_cache_long.expire = 2592000
333
333
334 # default is memorylru_base cache, configure only if required
334 # default is memorylru_base cache, configure only if required
335 # using multi-node or multi-worker setup
335 # using multi-node or multi-worker setup
336 #beaker.cache.repo_cache_long.type = ext:memcached
336 #beaker.cache.repo_cache_long.type = ext:memcached
337 #beaker.cache.repo_cache_long.url = localhost:11211
337 #beaker.cache.repo_cache_long.url = localhost:11211
338 #beaker.cache.repo_cache_long.expire = 1209600
338 #beaker.cache.repo_cache_long.expire = 1209600
339 #beaker.cache.repo_cache_long.key_length = 256
339 #beaker.cache.repo_cache_long.key_length = 256
340
340
341 ####################################
341 ####################################
342 ### BEAKER SESSION ####
342 ### BEAKER SESSION ####
343 ####################################
343 ####################################
344
344
345 ## .session.type is type of storage options for the session, current allowed
345 ## .session.type is type of storage options for the session, current allowed
346 ## types are file, ext:memcached, ext:database, and memory (default).
346 ## types are file, ext:memcached, ext:database, and memory (default).
347 beaker.session.type = file
347 beaker.session.type = file
348 beaker.session.data_dir = %(here)s/data/sessions/data
348 beaker.session.data_dir = %(here)s/data/sessions/data
349
349
350 ## db based session, fast, and allows easy management over logged in users ##
350 ## db based session, fast, and allows easy management over logged in users ##
351 #beaker.session.type = ext:database
351 #beaker.session.type = ext:database
352 #beaker.session.table_name = db_session
352 #beaker.session.table_name = db_session
353 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
353 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
354 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
354 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
355 #beaker.session.sa.pool_recycle = 3600
355 #beaker.session.sa.pool_recycle = 3600
356 #beaker.session.sa.echo = false
356 #beaker.session.sa.echo = false
357
357
358 beaker.session.key = rhodecode
358 beaker.session.key = rhodecode
359 beaker.session.secret = develop-rc-uytcxaz
359 beaker.session.secret = develop-rc-uytcxaz
360 beaker.session.lock_dir = %(here)s/data/sessions/lock
360 beaker.session.lock_dir = %(here)s/data/sessions/lock
361
361
362 ## Secure encrypted cookie. Requires AES and AES python libraries
362 ## Secure encrypted cookie. Requires AES and AES python libraries
363 ## you must disable beaker.session.secret to use this
363 ## you must disable beaker.session.secret to use this
364 #beaker.session.encrypt_key = <key_for_encryption>
364 #beaker.session.encrypt_key = <key_for_encryption>
365 #beaker.session.validate_key = <validation_key>
365 #beaker.session.validate_key = <validation_key>
366
366
367 ## sets session as invalid(also logging out user) if it haven not been
367 ## sets session as invalid(also logging out user) if it haven not been
368 ## accessed for given amount of time in seconds
368 ## accessed for given amount of time in seconds
369 beaker.session.timeout = 2592000
369 beaker.session.timeout = 2592000
370 beaker.session.httponly = true
370 beaker.session.httponly = true
371 #beaker.session.cookie_path = /<your-prefix>
371 #beaker.session.cookie_path = /<your-prefix>
372
372
373 ## uncomment for https secure cookie
373 ## uncomment for https secure cookie
374 beaker.session.secure = false
374 beaker.session.secure = false
375
375
376 ## auto save the session to not to use .save()
376 ## auto save the session to not to use .save()
377 beaker.session.auto = false
377 beaker.session.auto = false
378
378
379 ## default cookie expiration time in seconds, set to `true` to set expire
379 ## default cookie expiration time in seconds, set to `true` to set expire
380 ## at browser close
380 ## at browser close
381 #beaker.session.cookie_expires = 3600
381 #beaker.session.cookie_expires = 3600
382
382
383 ###################################
383 ###################################
384 ## SEARCH INDEXING CONFIGURATION ##
384 ## SEARCH INDEXING CONFIGURATION ##
385 ###################################
385 ###################################
386 ## Full text search indexer is available in rhodecode-tools under
386 ## Full text search indexer is available in rhodecode-tools under
387 ## `rhodecode-tools index` command
387 ## `rhodecode-tools index` command
388
388
389 # WHOOSH Backend, doesn't require additional services to run
389 # WHOOSH Backend, doesn't require additional services to run
390 # it works good with few dozen repos
390 # it works good with few dozen repos
391 search.module = rhodecode.lib.index.whoosh
391 search.module = rhodecode.lib.index.whoosh
392 search.location = %(here)s/data/index
392 search.location = %(here)s/data/index
393
393
394 ###################################
394 ###################################
395 ## APPENLIGHT CONFIG ##
395 ## APPENLIGHT CONFIG ##
396 ###################################
396 ###################################
397
397
398 ## Appenlight is tailored to work with RhodeCode, see
398 ## Appenlight is tailored to work with RhodeCode, see
399 ## http://appenlight.com for details how to obtain an account
399 ## http://appenlight.com for details how to obtain an account
400
400
401 ## appenlight integration enabled
401 ## appenlight integration enabled
402 appenlight = false
402 appenlight = false
403
403
404 appenlight.server_url = https://api.appenlight.com
404 appenlight.server_url = https://api.appenlight.com
405 appenlight.api_key = YOUR_API_KEY
405 appenlight.api_key = YOUR_API_KEY
406 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
406 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
407
407
408 # used for JS client
408 # used for JS client
409 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
409 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
410
410
411 ## TWEAK AMOUNT OF INFO SENT HERE
411 ## TWEAK AMOUNT OF INFO SENT HERE
412
412
413 ## enables 404 error logging (default False)
413 ## enables 404 error logging (default False)
414 appenlight.report_404 = false
414 appenlight.report_404 = false
415
415
416 ## time in seconds after request is considered being slow (default 1)
416 ## time in seconds after request is considered being slow (default 1)
417 appenlight.slow_request_time = 1
417 appenlight.slow_request_time = 1
418
418
419 ## record slow requests in application
419 ## record slow requests in application
420 ## (needs to be enabled for slow datastore recording and time tracking)
420 ## (needs to be enabled for slow datastore recording and time tracking)
421 appenlight.slow_requests = true
421 appenlight.slow_requests = true
422
422
423 ## enable hooking to application loggers
423 ## enable hooking to application loggers
424 appenlight.logging = true
424 appenlight.logging = true
425
425
426 ## minimum log level for log capture
426 ## minimum log level for log capture
427 appenlight.logging.level = WARNING
427 appenlight.logging.level = WARNING
428
428
429 ## send logs only from erroneous/slow requests
429 ## send logs only from erroneous/slow requests
430 ## (saves API quota for intensive logging)
430 ## (saves API quota for intensive logging)
431 appenlight.logging_on_error = false
431 appenlight.logging_on_error = false
432
432
433 ## list of additonal keywords that should be grabbed from environ object
433 ## list of additonal keywords that should be grabbed from environ object
434 ## can be string with comma separated list of words in lowercase
434 ## can be string with comma separated list of words in lowercase
435 ## (by default client will always send following info:
435 ## (by default client will always send following info:
436 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
436 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
437 ## start with HTTP* this list be extended with additional keywords here
437 ## start with HTTP* this list be extended with additional keywords here
438 appenlight.environ_keys_whitelist =
438 appenlight.environ_keys_whitelist =
439
439
440 ## list of keywords that should be blanked from request object
440 ## list of keywords that should be blanked from request object
441 ## can be string with comma separated list of words in lowercase
441 ## can be string with comma separated list of words in lowercase
442 ## (by default client will always blank keys that contain following words
442 ## (by default client will always blank keys that contain following words
443 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
443 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
444 ## this list be extended with additional keywords set here
444 ## this list be extended with additional keywords set here
445 appenlight.request_keys_blacklist =
445 appenlight.request_keys_blacklist =
446
446
447 ## list of namespaces that should be ignores when gathering log entries
447 ## list of namespaces that should be ignores when gathering log entries
448 ## can be string with comma separated list of namespaces
448 ## can be string with comma separated list of namespaces
449 ## (by default the client ignores own entries: appenlight_client.client)
449 ## (by default the client ignores own entries: appenlight_client.client)
450 appenlight.log_namespace_blacklist =
450 appenlight.log_namespace_blacklist =
451
451
452
452
453 ################################################################################
453 ################################################################################
454 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
454 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
455 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
455 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
456 ## execute malicious code after an exception is raised. ##
456 ## execute malicious code after an exception is raised. ##
457 ################################################################################
457 ################################################################################
458 #set debug = false
458 #set debug = false
459
459
460
460
461 ##############
461 ##############
462 ## STYLING ##
462 ## STYLING ##
463 ##############
463 ##############
464 debug_style = true
464 debug_style = true
465
465
466 #########################################################
466 #########################################################
467 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
467 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
468 #########################################################
468 #########################################################
469 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
469 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
470 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
470 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
471 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
471 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
472
472
473 # see sqlalchemy docs for other advanced settings
473 # see sqlalchemy docs for other advanced settings
474
474
475 ## print the sql statements to output
475 ## print the sql statements to output
476 sqlalchemy.db1.echo = false
476 sqlalchemy.db1.echo = false
477 ## recycle the connections after this ammount of seconds
477 ## recycle the connections after this ammount of seconds
478 sqlalchemy.db1.pool_recycle = 3600
478 sqlalchemy.db1.pool_recycle = 3600
479 sqlalchemy.db1.convert_unicode = true
479 sqlalchemy.db1.convert_unicode = true
480
480
481 ## the number of connections to keep open inside the connection pool.
481 ## the number of connections to keep open inside the connection pool.
482 ## 0 indicates no limit
482 ## 0 indicates no limit
483 #sqlalchemy.db1.pool_size = 5
483 #sqlalchemy.db1.pool_size = 5
484
484
485 ## the number of connections to allow in connection pool "overflow", that is
485 ## the number of connections to allow in connection pool "overflow", that is
486 ## connections that can be opened above and beyond the pool_size setting,
486 ## connections that can be opened above and beyond the pool_size setting,
487 ## which defaults to five.
487 ## which defaults to five.
488 #sqlalchemy.db1.max_overflow = 10
488 #sqlalchemy.db1.max_overflow = 10
489
489
490
490
491 ##################
491 ##################
492 ### VCS CONFIG ###
492 ### VCS CONFIG ###
493 ##################
493 ##################
494 vcs.server.enable = true
494 vcs.server.enable = true
495 vcs.server = localhost:9900
495 vcs.server = localhost:9900
496
496
497 ## Web server connectivity protocol, responsible for web based VCS operatations
497 ## Web server connectivity protocol, responsible for web based VCS operatations
498 ## Available protocols are:
498 ## Available protocols are:
499 ## `pyro4` - using pyro4 server
499 ## `pyro4` - using pyro4 server
500 ## `http` - using http-rpc backend
500 ## `http` - using http-rpc backend
501 #vcs.server.protocol = http
501 #vcs.server.protocol = http
502
502
503 ## Push/Pull operations protocol, available options are:
503 ## Push/Pull operations protocol, available options are:
504 ## `pyro4` - using pyro4 server
504 ## `pyro4` - using pyro4 server
505 ## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended
505 ## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended
506 ## `vcsserver.scm_app` - internal app (EE only)
506 ## `vcsserver.scm_app` - internal app (EE only)
507 #vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http
507 #vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http
508
508
509 ## Push/Pull operations hooks protocol, available options are:
509 ## Push/Pull operations hooks protocol, available options are:
510 ## `pyro4` - using pyro4 server
510 ## `pyro4` - using pyro4 server
511 ## `http` - using http-rpc backend
511 ## `http` - using http-rpc backend
512 #vcs.hooks.protocol = http
512 #vcs.hooks.protocol = http
513
513
514 vcs.server.log_level = debug
514 vcs.server.log_level = debug
515 ## Start VCSServer with this instance as a subprocess, usefull for development
515 ## Start VCSServer with this instance as a subprocess, usefull for development
516 vcs.start_server = true
516 vcs.start_server = true
517 vcs.backends = hg, git, svn
517 vcs.backends = hg, git, svn
518 vcs.connection_timeout = 3600
518 vcs.connection_timeout = 3600
519 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
519 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
520 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
520 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
521 #vcs.svn.compatible_version = pre-1.8-compatible
521 #vcs.svn.compatible_version = pre-1.8-compatible
522
522
523 ################################
523 ################################
524 ### LOGGING CONFIGURATION ####
524 ### LOGGING CONFIGURATION ####
525 ################################
525 ################################
526 [loggers]
526 [loggers]
527 keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates
527 keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates
528
528
529 [handlers]
529 [handlers]
530 keys = console, console_sql
530 keys = console, console_sql
531
531
532 [formatters]
532 [formatters]
533 keys = generic, color_formatter, color_formatter_sql
533 keys = generic, color_formatter, color_formatter_sql
534
534
535 #############
535 #############
536 ## LOGGERS ##
536 ## LOGGERS ##
537 #############
537 #############
538 [logger_root]
538 [logger_root]
539 level = NOTSET
539 level = NOTSET
540 handlers = console
540 handlers = console
541
541
542 [logger_routes]
542 [logger_routes]
543 level = DEBUG
543 level = DEBUG
544 handlers =
544 handlers =
545 qualname = routes.middleware
545 qualname = routes.middleware
546 ## "level = DEBUG" logs the route matched and routing variables.
546 ## "level = DEBUG" logs the route matched and routing variables.
547 propagate = 1
547 propagate = 1
548
548
549 [logger_beaker]
549 [logger_beaker]
550 level = DEBUG
550 level = DEBUG
551 handlers =
551 handlers =
552 qualname = beaker.container
552 qualname = beaker.container
553 propagate = 1
553 propagate = 1
554
554
555 [logger_pyro4]
555 [logger_pyro4]
556 level = DEBUG
556 level = DEBUG
557 handlers =
557 handlers =
558 qualname = Pyro4
558 qualname = Pyro4
559 propagate = 1
559 propagate = 1
560
560
561 [logger_templates]
561 [logger_templates]
562 level = INFO
562 level = INFO
563 handlers =
563 handlers =
564 qualname = pylons.templating
564 qualname = pylons.templating
565 propagate = 1
565 propagate = 1
566
566
567 [logger_rhodecode]
567 [logger_rhodecode]
568 level = DEBUG
568 level = DEBUG
569 handlers =
569 handlers =
570 qualname = rhodecode
570 qualname = rhodecode
571 propagate = 1
571 propagate = 1
572
572
573 [logger_sqlalchemy]
573 [logger_sqlalchemy]
574 level = INFO
574 level = INFO
575 handlers = console_sql
575 handlers = console_sql
576 qualname = sqlalchemy.engine
576 qualname = sqlalchemy.engine
577 propagate = 0
577 propagate = 0
578
578
579 ##############
579 ##############
580 ## HANDLERS ##
580 ## HANDLERS ##
581 ##############
581 ##############
582
582
583 [handler_console]
583 [handler_console]
584 class = StreamHandler
584 class = StreamHandler
585 args = (sys.stderr,)
585 args = (sys.stderr,)
586 level = DEBUG
586 level = DEBUG
587 formatter = color_formatter
587 formatter = color_formatter
588
588
589 [handler_console_sql]
589 [handler_console_sql]
590 class = StreamHandler
590 class = StreamHandler
591 args = (sys.stderr,)
591 args = (sys.stderr,)
592 level = DEBUG
592 level = DEBUG
593 formatter = color_formatter_sql
593 formatter = color_formatter_sql
594
594
595 ################
595 ################
596 ## FORMATTERS ##
596 ## FORMATTERS ##
597 ################
597 ################
598
598
599 [formatter_generic]
599 [formatter_generic]
600 class = rhodecode.lib.logging_formatter.Pyro4AwareFormatter
600 class = rhodecode.lib.logging_formatter.Pyro4AwareFormatter
601 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
601 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
602 datefmt = %Y-%m-%d %H:%M:%S
602 datefmt = %Y-%m-%d %H:%M:%S
603
603
604 [formatter_color_formatter]
604 [formatter_color_formatter]
605 class = rhodecode.lib.logging_formatter.ColorFormatter
605 class = rhodecode.lib.logging_formatter.ColorFormatter
606 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
606 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
607 datefmt = %Y-%m-%d %H:%M:%S
607 datefmt = %Y-%m-%d %H:%M:%S
608
608
609 [formatter_color_formatter_sql]
609 [formatter_color_formatter_sql]
610 class = rhodecode.lib.logging_formatter.ColorFormatterSql
610 class = rhodecode.lib.logging_formatter.ColorFormatterSql
611 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
611 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
612 datefmt = %Y-%m-%d %H:%M:%S
612 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,387 +1,367 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 import pyramid.httpexceptions as httpexceptions
35 import pyramid.httpexceptions as httpexceptions
36 from pyramid.renderers import render_to_response, render
36 from pyramid.renderers import render_to_response, render
37 from routes.middleware import RoutesMiddleware
37 from routes.middleware import RoutesMiddleware
38 import routes.util
38 import routes.util
39
39
40 import rhodecode
40 import rhodecode
41 import rhodecode.integrations # do not remove this as it registers celery tasks
41 import rhodecode.integrations # do not remove this as it registers celery tasks
42 from rhodecode.config import patches
42 from rhodecode.config import patches
43 from rhodecode.config.environment import (
43 from rhodecode.config.environment import (
44 load_environment, load_pyramid_environment)
44 load_environment, load_pyramid_environment)
45 from rhodecode.lib.middleware import csrf
45 from rhodecode.lib.middleware import csrf
46 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
46 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
47 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
47 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
48 from rhodecode.lib.middleware.https_fixup import HttpsFixup
48 from rhodecode.lib.middleware.https_fixup import HttpsFixup
49 from rhodecode.lib.middleware.vcs import VCSMiddleware
49 from rhodecode.lib.middleware.vcs import VCSMiddleware
50 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
50 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
51
51
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
56 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
57 """Create a Pylons WSGI application and return it
57 """Create a Pylons WSGI application and return it
58
58
59 ``global_conf``
59 ``global_conf``
60 The inherited configuration for this application. Normally from
60 The inherited configuration for this application. Normally from
61 the [DEFAULT] section of the Paste ini file.
61 the [DEFAULT] section of the Paste ini file.
62
62
63 ``full_stack``
63 ``full_stack``
64 Whether or not this application provides a full WSGI stack (by
64 Whether or not this application provides a full WSGI stack (by
65 default, meaning it handles its own exceptions and errors).
65 default, meaning it handles its own exceptions and errors).
66 Disable full_stack when this application is "managed" by
66 Disable full_stack when this application is "managed" by
67 another WSGI middleware.
67 another WSGI middleware.
68
68
69 ``app_conf``
69 ``app_conf``
70 The application's local configuration. Normally specified in
70 The application's local configuration. Normally specified in
71 the [app:<name>] section of the Paste ini file (where <name>
71 the [app:<name>] section of the Paste ini file (where <name>
72 defaults to main).
72 defaults to main).
73
73
74 """
74 """
75 # Apply compatibility patches
75 # Apply compatibility patches
76 patches.kombu_1_5_1_python_2_7_11()
76 patches.kombu_1_5_1_python_2_7_11()
77 patches.inspect_getargspec()
77 patches.inspect_getargspec()
78
78
79 # Configure the Pylons environment
79 # Configure the Pylons environment
80 config = load_environment(global_conf, app_conf)
80 config = load_environment(global_conf, app_conf)
81
81
82 # The Pylons WSGI app
82 # The Pylons WSGI app
83 app = PylonsApp(config=config)
83 app = PylonsApp(config=config)
84 if rhodecode.is_test:
84 if rhodecode.is_test:
85 app = csrf.CSRFDetector(app)
85 app = csrf.CSRFDetector(app)
86
86
87 expected_origin = config.get('expected_origin')
87 expected_origin = config.get('expected_origin')
88 if expected_origin:
88 if expected_origin:
89 # The API can be accessed from other Origins.
89 # The API can be accessed from other Origins.
90 app = csrf.OriginChecker(app, expected_origin,
90 app = csrf.OriginChecker(app, expected_origin,
91 skip_urls=[routes.util.url_for('api')])
91 skip_urls=[routes.util.url_for('api')])
92
92
93
93
94 if asbool(full_stack):
94 if asbool(full_stack):
95
95
96 # Appenlight monitoring and error handler
96 # Appenlight monitoring and error handler
97 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
97 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
98
98
99 # we want our low level middleware to get to the request ASAP. We don't
99 # we want our low level middleware to get to the request ASAP. We don't
100 # need any pylons stack middleware in them
100 # need any pylons stack middleware in them
101 app = VCSMiddleware(app, config, appenlight_client)
101 app = VCSMiddleware(app, config, appenlight_client)
102
102
103 # Establish the Registry for this application
103 # Establish the Registry for this application
104 app = RegistryManager(app)
104 app = RegistryManager(app)
105
105
106 app.config = config
106 app.config = config
107
107
108 return app
108 return app
109
109
110
110
111 def make_pyramid_app(global_config, **settings):
111 def make_pyramid_app(global_config, **settings):
112 """
112 """
113 Constructs the WSGI application based on Pyramid and wraps the Pylons based
113 Constructs the WSGI application based on Pyramid and wraps the Pylons based
114 application.
114 application.
115
115
116 Specials:
116 Specials:
117
117
118 * We migrate from Pylons to Pyramid. While doing this, we keep both
118 * We migrate from Pylons to Pyramid. While doing this, we keep both
119 frameworks functional. This involves moving some WSGI middlewares around
119 frameworks functional. This involves moving some WSGI middlewares around
120 and providing access to some data internals, so that the old code is
120 and providing access to some data internals, so that the old code is
121 still functional.
121 still functional.
122
122
123 * The application can also be integrated like a plugin via the call to
123 * The application can also be integrated like a plugin via the call to
124 `includeme`. This is accompanied with the other utility functions which
124 `includeme`. This is accompanied with the other utility functions which
125 are called. Changing this should be done with great care to not break
125 are called. Changing this should be done with great care to not break
126 cases when these fragments are assembled from another place.
126 cases when these fragments are assembled from another place.
127
127
128 """
128 """
129 # The edition string should be available in pylons too, so we add it here
129 # The edition string should be available in pylons too, so we add it here
130 # before copying the settings.
130 # before copying the settings.
131 settings.setdefault('rhodecode.edition', 'Community Edition')
131 settings.setdefault('rhodecode.edition', 'Community Edition')
132
132
133 # As long as our Pylons application does expect "unprepared" settings, make
133 # As long as our Pylons application does expect "unprepared" settings, make
134 # sure that we keep an unmodified copy. This avoids unintentional change of
134 # sure that we keep an unmodified copy. This avoids unintentional change of
135 # behavior in the old application.
135 # behavior in the old application.
136 settings_pylons = settings.copy()
136 settings_pylons = settings.copy()
137
137
138 sanitize_settings_and_apply_defaults(settings)
138 sanitize_settings_and_apply_defaults(settings)
139 config = Configurator(settings=settings)
139 config = Configurator(settings=settings)
140 add_pylons_compat_data(config.registry, global_config, settings_pylons)
140 add_pylons_compat_data(config.registry, global_config, settings_pylons)
141
141
142 load_pyramid_environment(global_config, settings)
142 load_pyramid_environment(global_config, settings)
143
143
144 includeme(config)
144 includeme(config)
145 includeme_last(config)
145 includeme_last(config)
146 pyramid_app = config.make_wsgi_app()
146 pyramid_app = config.make_wsgi_app()
147 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
147 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
148 return pyramid_app
148 return pyramid_app
149
149
150
150
151 def add_pylons_compat_data(registry, global_config, settings):
151 def add_pylons_compat_data(registry, global_config, settings):
152 """
152 """
153 Attach data to the registry to support the Pylons integration.
153 Attach data to the registry to support the Pylons integration.
154 """
154 """
155 registry._pylons_compat_global_config = global_config
155 registry._pylons_compat_global_config = global_config
156 registry._pylons_compat_settings = settings
156 registry._pylons_compat_settings = settings
157
157
158
158
159 def webob_to_pyramid_http_response(webob_response):
159 def webob_to_pyramid_http_response(webob_response):
160 ResponseClass = httpexceptions.status_map[webob_response.status_int]
160 ResponseClass = httpexceptions.status_map[webob_response.status_int]
161 pyramid_response = ResponseClass(webob_response.status)
161 pyramid_response = ResponseClass(webob_response.status)
162 pyramid_response.status = webob_response.status
162 pyramid_response.status = webob_response.status
163 pyramid_response.headers.update(webob_response.headers)
163 pyramid_response.headers.update(webob_response.headers)
164 if pyramid_response.headers['content-type'] == 'text/html':
164 if pyramid_response.headers['content-type'] == 'text/html':
165 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
165 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
166 return pyramid_response
166 return pyramid_response
167
167
168
168
169 def error_handler(exception, request):
169 def error_handler(exception, request):
170 # TODO: dan: replace the old pylons error controller with this
170 # TODO: dan: replace the old pylons error controller with this
171 from rhodecode.model.settings import SettingsModel
171 from rhodecode.model.settings import SettingsModel
172 from rhodecode.lib.utils2 import AttributeDict
172 from rhodecode.lib.utils2 import AttributeDict
173
173
174 try:
174 try:
175 rc_config = SettingsModel().get_all_settings()
175 rc_config = SettingsModel().get_all_settings()
176 except Exception:
176 except Exception:
177 log.exception('failed to fetch settings')
177 log.exception('failed to fetch settings')
178 rc_config = {}
178 rc_config = {}
179
179
180 base_response = HTTPInternalServerError()
180 base_response = HTTPInternalServerError()
181 # prefer original exception for the response since it may have headers set
181 # prefer original exception for the response since it may have headers set
182 if isinstance(exception, HTTPError):
182 if isinstance(exception, HTTPError):
183 base_response = exception
183 base_response = exception
184
184
185 c = AttributeDict()
185 c = AttributeDict()
186 c.error_message = base_response.status
186 c.error_message = base_response.status
187 c.error_explanation = base_response.explanation or str(base_response)
187 c.error_explanation = base_response.explanation or str(base_response)
188 c.visual = AttributeDict()
188 c.visual = AttributeDict()
189
189
190 c.visual.rhodecode_support_url = (
190 c.visual.rhodecode_support_url = (
191 request.registry.settings.get('rhodecode_support_url') or
191 request.registry.settings.get('rhodecode_support_url') or
192 request.route_url('rhodecode_support')
192 request.route_url('rhodecode_support')
193 )
193 )
194 c.redirect_time = 0
194 c.redirect_time = 0
195 c.rhodecode_name = rc_config.get('rhodecode_title', '')
195 c.rhodecode_name = rc_config.get('rhodecode_title', '')
196 if not c.rhodecode_name:
196 if not c.rhodecode_name:
197 c.rhodecode_name = 'Rhodecode'
197 c.rhodecode_name = 'Rhodecode'
198
198
199 response = render_to_response(
199 response = render_to_response(
200 '/errors/error_document.html', {'c': c}, request=request,
200 '/errors/error_document.html', {'c': c}, request=request,
201 response=base_response)
201 response=base_response)
202
202
203 return response
203 return response
204
204
205
205
206 def includeme(config):
206 def includeme(config):
207 settings = config.registry.settings
207 settings = config.registry.settings
208
208
209 if asbool(settings.get('appenlight', 'false')):
209 if asbool(settings.get('appenlight', 'false')):
210 config.include('appenlight_client.ext.pyramid_tween')
210 config.include('appenlight_client.ext.pyramid_tween')
211
211
212 # Includes which are required. The application would fail without them.
212 # Includes which are required. The application would fail without them.
213 config.include('pyramid_mako')
213 config.include('pyramid_mako')
214 config.include('pyramid_beaker')
214 config.include('pyramid_beaker')
215 config.include('rhodecode.admin')
215 config.include('rhodecode.admin')
216 config.include('rhodecode.authentication')
216 config.include('rhodecode.authentication')
217 config.include('rhodecode.integrations')
217 config.include('rhodecode.integrations')
218 config.include('rhodecode.login')
218 config.include('rhodecode.login')
219 config.include('rhodecode.tweens')
219 config.include('rhodecode.tweens')
220 config.include('rhodecode.api')
220 config.include('rhodecode.api')
221 config.add_route(
221 config.add_route(
222 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
222 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
223
223
224 # Set the authorization policy.
224 # Set the authorization policy.
225 authz_policy = ACLAuthorizationPolicy()
225 authz_policy = ACLAuthorizationPolicy()
226 config.set_authorization_policy(authz_policy)
226 config.set_authorization_policy(authz_policy)
227
227
228 # Set the default renderer for HTML templates to mako.
228 # Set the default renderer for HTML templates to mako.
229 config.add_mako_renderer('.html')
229 config.add_mako_renderer('.html')
230
230
231 # plugin information
231 # plugin information
232 config.registry.rhodecode_plugins = {}
232 config.registry.rhodecode_plugins = {}
233
233
234 config.add_directive(
234 config.add_directive(
235 'register_rhodecode_plugin', register_rhodecode_plugin)
235 'register_rhodecode_plugin', register_rhodecode_plugin)
236 # include RhodeCode plugins
236 # include RhodeCode plugins
237 includes = aslist(settings.get('rhodecode.includes', []))
237 includes = aslist(settings.get('rhodecode.includes', []))
238 for inc in includes:
238 for inc in includes:
239 config.include(inc)
239 config.include(inc)
240
240
241 pylons_app = make_app(
241 pylons_app = make_app(
242 config.registry._pylons_compat_global_config,
242 config.registry._pylons_compat_global_config,
243 **config.registry._pylons_compat_settings)
243 **config.registry._pylons_compat_settings)
244 config.registry._pylons_compat_config = pylons_app.config
244 config.registry._pylons_compat_config = pylons_app.config
245
245
246 pylons_app_as_view = wsgiapp(pylons_app)
246 pylons_app_as_view = wsgiapp(pylons_app)
247
247
248 # Protect from VCS Server error related pages when server is not available
248 # Protect from VCS Server error related pages when server is not available
249 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
249 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
250 if not vcs_server_enabled:
250 if not vcs_server_enabled:
251 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
251 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
252
252
253
253
254 def pylons_app_with_error_handler(context, request):
254 def pylons_app_with_error_handler(context, request):
255 """
255 """
256 Handle exceptions from rc pylons app:
256 Handle exceptions from rc pylons app:
257
257
258 - old webob type exceptions get converted to pyramid exceptions
258 - old webob type exceptions get converted to pyramid exceptions
259 - pyramid exceptions are passed to the error handler view
259 - pyramid exceptions are passed to the error handler view
260 """
260 """
261 try:
261 try:
262 response = pylons_app_as_view(context, request)
262 response = pylons_app_as_view(context, request)
263 if 400 <= response.status_int <= 599: # webob type error responses
263 if 400 <= response.status_int <= 599: # webob type error responses
264 return error_handler(
264 return error_handler(
265 webob_to_pyramid_http_response(response), request)
265 webob_to_pyramid_http_response(response), request)
266 except HTTPError as e: # pyramid type exceptions
266 except HTTPError as e: # pyramid type exceptions
267 return error_handler(e, request)
267 return error_handler(e, request)
268 except Exception:
268 except Exception:
269 if settings.get('debugtoolbar.enabled', False):
269 if settings.get('debugtoolbar.enabled', False):
270 raise
270 raise
271 return error_handler(HTTPInternalServerError(), request)
271 return error_handler(HTTPInternalServerError(), request)
272 return response
272 return response
273
273
274 # This is the glue which allows us to migrate in chunks. By registering the
274 # This is the glue which allows us to migrate in chunks. By registering the
275 # pylons based application as the "Not Found" view in Pyramid, we will
275 # pylons based application as the "Not Found" view in Pyramid, we will
276 # fallback to the old application each time the new one does not yet know
276 # fallback to the old application each time the new one does not yet know
277 # how to handle a request.
277 # how to handle a request.
278 config.add_notfound_view(pylons_app_with_error_handler)
278 config.add_notfound_view(pylons_app_with_error_handler)
279
279
280 if not settings.get('debugtoolbar.enabled', False):
280 if not settings.get('debugtoolbar.enabled', False):
281 # if no toolbar, then any exception gets caught and rendered
281 # if no toolbar, then any exception gets caught and rendered
282 config.add_view(error_handler, context=Exception)
282 config.add_view(error_handler, context=Exception)
283
283
284 config.add_view(error_handler, context=HTTPError)
284 config.add_view(error_handler, context=HTTPError)
285
285
286
286
287 def includeme_last(config):
287 def includeme_last(config):
288 """
288 """
289 The static file catchall needs to be last in the view configuration.
289 The static file catchall needs to be last in the view configuration.
290 """
290 """
291 settings = config.registry.settings
291 settings = config.registry.settings
292
292 config.add_static_view('_static', path='rhodecode:public')
293 # Note: johbo: I would prefer to register a prefix for static files at some
294 # point, e.g. move them under '_static/'. This would fully avoid that we
295 # can have name clashes with a repository name. Imaging someone calling his
296 # repo "css" ;-) Also having an external web server to serve out the static
297 # files seems to be easier to set up if they have a common prefix.
298 #
299 # Example: config.add_static_view('_static', path='rhodecode:public')
300 #
301 # It might be an option to register both paths for a while and then migrate
302 # over to the new location.
303
304 # Serving static files with a catchall.
305 if settings['static_files']:
306 config.add_route('catchall_static', '/*subpath')
307 config.add_view(
308 static_view('rhodecode:public'), route_name='catchall_static')
309
293
310
294
311 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
295 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
312 """
296 """
313 Apply outer WSGI middlewares around the application.
297 Apply outer WSGI middlewares around the application.
314
298
315 Part of this has been moved up from the Pylons layer, so that the
299 Part of this has been moved up from the Pylons layer, so that the
316 data is also available if old Pylons code is hit through an already ported
300 data is also available if old Pylons code is hit through an already ported
317 view.
301 view.
318 """
302 """
319 settings = config.registry.settings
303 settings = config.registry.settings
320
304
321 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
305 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
322 pyramid_app = HttpsFixup(pyramid_app, settings)
306 pyramid_app = HttpsFixup(pyramid_app, settings)
323
307
324 # Add RoutesMiddleware to support the pylons compatibility tween during
308 # Add RoutesMiddleware to support the pylons compatibility tween during
325
309
326 # migration to pyramid.
310 # migration to pyramid.
327 pyramid_app = RoutesMiddleware(
311 pyramid_app = RoutesMiddleware(
328 pyramid_app, config.registry._pylons_compat_config['routes.map'])
312 pyramid_app, config.registry._pylons_compat_config['routes.map'])
329
313
330 if asbool(settings.get('appenlight', 'false')):
314 if asbool(settings.get('appenlight', 'false')):
331 pyramid_app, _ = wrap_in_appenlight_if_enabled(
315 pyramid_app, _ = wrap_in_appenlight_if_enabled(
332 pyramid_app, config.registry._pylons_compat_config)
316 pyramid_app, config.registry._pylons_compat_config)
333
317
334 # TODO: johbo: Don't really see why we enable the gzip middleware when
318 if asbool(settings.get('gzip_responses', 'true')):
335 # serving static files, might be something that should have its own setting
336 # as well?
337 if settings['static_files']:
338 pyramid_app = make_gzip_middleware(
319 pyramid_app = make_gzip_middleware(
339 pyramid_app, settings, compress_level=1)
320 pyramid_app, settings, compress_level=1)
340
321
341 return pyramid_app
322 return pyramid_app
342
323
343
324
344 def sanitize_settings_and_apply_defaults(settings):
325 def sanitize_settings_and_apply_defaults(settings):
345 """
326 """
346 Applies settings defaults and does all type conversion.
327 Applies settings defaults and does all type conversion.
347
328
348 We would move all settings parsing and preparation into this place, so that
329 We would move all settings parsing and preparation into this place, so that
349 we have only one place left which deals with this part. The remaining parts
330 we have only one place left which deals with this part. The remaining parts
350 of the application would start to rely fully on well prepared settings.
331 of the application would start to rely fully on well prepared settings.
351
332
352 This piece would later be split up per topic to avoid a big fat monster
333 This piece would later be split up per topic to avoid a big fat monster
353 function.
334 function.
354 """
335 """
355
336
356 # Pyramid's mako renderer has to search in the templates folder so that the
337 # Pyramid's mako renderer has to search in the templates folder so that the
357 # old templates still work. Ported and new templates are expected to use
338 # old templates still work. Ported and new templates are expected to use
358 # real asset specifications for the includes.
339 # real asset specifications for the includes.
359 mako_directories = settings.setdefault('mako.directories', [
340 mako_directories = settings.setdefault('mako.directories', [
360 # Base templates of the original Pylons application
341 # Base templates of the original Pylons application
361 'rhodecode:templates',
342 'rhodecode:templates',
362 ])
343 ])
363 log.debug(
344 log.debug(
364 "Using the following Mako template directories: %s",
345 "Using the following Mako template directories: %s",
365 mako_directories)
346 mako_directories)
366
347
367 # Default includes, possible to change as a user
348 # Default includes, possible to change as a user
368 pyramid_includes = settings.setdefault('pyramid.includes', [
349 pyramid_includes = settings.setdefault('pyramid.includes', [
369 'rhodecode.lib.middleware.request_wrapper',
350 'rhodecode.lib.middleware.request_wrapper',
370 ])
351 ])
371 log.debug(
352 log.debug(
372 "Using the following pyramid.includes: %s",
353 "Using the following pyramid.includes: %s",
373 pyramid_includes)
354 pyramid_includes)
374
355
375 # TODO: johbo: Re-think this, usually the call to config.include
356 # TODO: johbo: Re-think this, usually the call to config.include
376 # should allow to pass in a prefix.
357 # should allow to pass in a prefix.
377 settings.setdefault('rhodecode.api.url', '/_admin/api')
358 settings.setdefault('rhodecode.api.url', '/_admin/api')
378
359
379 _bool_setting(settings, 'vcs.server.enable', 'true')
360 _bool_setting(settings, 'vcs.server.enable', 'true')
380 _bool_setting(settings, 'static_files', 'true')
381 _bool_setting(settings, 'is_test', 'false')
361 _bool_setting(settings, 'is_test', 'false')
382
362
383 return settings
363 return settings
384
364
385
365
386 def _bool_setting(settings, name, default):
366 def _bool_setting(settings, name, default):
387 settings[name] = asbool(settings.get(name, default))
367 settings[name] = asbool(settings.get(name, default))
@@ -1,1931 +1,1947 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 Helper functions
22 Helper functions
23
23
24 Consists of functions to typically be used within templates, but also
24 Consists of functions to typically be used within templates, but also
25 available to Controllers. This module is available to both as 'h'.
25 available to Controllers. This module is available to both as 'h'.
26 """
26 """
27
27
28 import random
28 import random
29 import hashlib
29 import hashlib
30 import StringIO
30 import StringIO
31 import urllib
31 import urllib
32 import math
32 import math
33 import logging
33 import logging
34 import re
34 import re
35 import urlparse
35 import urlparse
36 import time
36 import time
37 import string
37 import string
38 import hashlib
38 import hashlib
39 import pygments
39 import pygments
40
40
41 from datetime import datetime
41 from datetime import datetime
42 from functools import partial
42 from functools import partial
43 from pygments.formatters.html import HtmlFormatter
43 from pygments.formatters.html import HtmlFormatter
44 from pygments import highlight as code_highlight
44 from pygments import highlight as code_highlight
45 from pygments.lexers import (
45 from pygments.lexers import (
46 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
46 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
47 from pylons import url as pylons_url
47 from pylons import url as pylons_url
48 from pylons.i18n.translation import _, ungettext
48 from pylons.i18n.translation import _, ungettext
49 from pyramid.threadlocal import get_current_request
49 from pyramid.threadlocal import get_current_request
50
50
51 from webhelpers.html import literal, HTML, escape
51 from webhelpers.html import literal, HTML, escape
52 from webhelpers.html.tools import *
52 from webhelpers.html.tools import *
53 from webhelpers.html.builder import make_tag
53 from webhelpers.html.builder import make_tag
54 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
54 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
55 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
55 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
56 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
56 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
57 submit, text, password, textarea, title, ul, xml_declaration, radio
57 submit, text, password, textarea, title, ul, xml_declaration, radio
58 from webhelpers.html.tools import auto_link, button_to, highlight, \
58 from webhelpers.html.tools import auto_link, button_to, highlight, \
59 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
59 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
60 from webhelpers.pylonslib import Flash as _Flash
60 from webhelpers.pylonslib import Flash as _Flash
61 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
61 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
62 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
62 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
63 replace_whitespace, urlify, truncate, wrap_paragraphs
63 replace_whitespace, urlify, truncate, wrap_paragraphs
64 from webhelpers.date import time_ago_in_words
64 from webhelpers.date import time_ago_in_words
65 from webhelpers.paginate import Page as _Page
65 from webhelpers.paginate import Page as _Page
66 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
66 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
67 convert_boolean_attrs, NotGiven, _make_safe_id_component
67 convert_boolean_attrs, NotGiven, _make_safe_id_component
68 from webhelpers2.number import format_byte_size
68 from webhelpers2.number import format_byte_size
69
69
70 from rhodecode.lib.annotate import annotate_highlight
70 from rhodecode.lib.annotate import annotate_highlight
71 from rhodecode.lib.action_parser import action_parser
71 from rhodecode.lib.action_parser import action_parser
72 from rhodecode.lib.ext_json import json
72 from rhodecode.lib.ext_json import json
73 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
73 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
74 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
74 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
75 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
75 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
76 AttributeDict, safe_int, md5, md5_safe
76 AttributeDict, safe_int, md5, md5_safe
77 from rhodecode.lib.markup_renderer import MarkupRenderer
77 from rhodecode.lib.markup_renderer import MarkupRenderer
78 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
78 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
79 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
79 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
80 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
80 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
81 from rhodecode.model.changeset_status import ChangesetStatusModel
81 from rhodecode.model.changeset_status import ChangesetStatusModel
82 from rhodecode.model.db import Permission, User, Repository
82 from rhodecode.model.db import Permission, User, Repository
83 from rhodecode.model.repo_group import RepoGroupModel
83 from rhodecode.model.repo_group import RepoGroupModel
84 from rhodecode.model.settings import IssueTrackerSettingsModel
84 from rhodecode.model.settings import IssueTrackerSettingsModel
85
85
86 log = logging.getLogger(__name__)
86 log = logging.getLogger(__name__)
87
87
88
88 DEFAULT_USER = User.DEFAULT_USER
89 DEFAULT_USER = User.DEFAULT_USER
89 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
90 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
90
91
92
91 def url(*args, **kw):
93 def url(*args, **kw):
92 return pylons_url(*args, **kw)
94 return pylons_url(*args, **kw)
93
95
96
94 def pylons_url_current(*args, **kw):
97 def pylons_url_current(*args, **kw):
95 """
98 """
96 This function overrides pylons.url.current() which returns the current
99 This function overrides pylons.url.current() which returns the current
97 path so that it will also work from a pyramid only context. This
100 path so that it will also work from a pyramid only context. This
98 should be removed once port to pyramid is complete.
101 should be removed once port to pyramid is complete.
99 """
102 """
100 if not args and not kw:
103 if not args and not kw:
101 request = get_current_request()
104 request = get_current_request()
102 return request.path
105 return request.path
103 return pylons_url.current(*args, **kw)
106 return pylons_url.current(*args, **kw)
104
107
105 url.current = pylons_url_current
108 url.current = pylons_url_current
106
109
107
110
111 def asset(path, ver=None):
112 """
113 Helper to generate a static asset file path for rhodecode assets
114
115 eg. h.asset('images/image.png', ver='3923')
116
117 :param path: path of asset
118 :param ver: optional version query param to append as ?ver=
119 """
120 request = get_current_request()
121 return request.static_url('rhodecode:public/{}'.format(path), ver=ver)
122
123
108 def html_escape(text, html_escape_table=None):
124 def html_escape(text, html_escape_table=None):
109 """Produce entities within text."""
125 """Produce entities within text."""
110 if not html_escape_table:
126 if not html_escape_table:
111 html_escape_table = {
127 html_escape_table = {
112 "&": "&amp;",
128 "&": "&amp;",
113 '"': "&quot;",
129 '"': "&quot;",
114 "'": "&apos;",
130 "'": "&apos;",
115 ">": "&gt;",
131 ">": "&gt;",
116 "<": "&lt;",
132 "<": "&lt;",
117 }
133 }
118 return "".join(html_escape_table.get(c, c) for c in text)
134 return "".join(html_escape_table.get(c, c) for c in text)
119
135
120
136
121 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
137 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
122 """
138 """
123 Truncate string ``s`` at the first occurrence of ``sub``.
139 Truncate string ``s`` at the first occurrence of ``sub``.
124
140
125 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
141 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
126 """
142 """
127 suffix_if_chopped = suffix_if_chopped or ''
143 suffix_if_chopped = suffix_if_chopped or ''
128 pos = s.find(sub)
144 pos = s.find(sub)
129 if pos == -1:
145 if pos == -1:
130 return s
146 return s
131
147
132 if inclusive:
148 if inclusive:
133 pos += len(sub)
149 pos += len(sub)
134
150
135 chopped = s[:pos]
151 chopped = s[:pos]
136 left = s[pos:].strip()
152 left = s[pos:].strip()
137
153
138 if left and suffix_if_chopped:
154 if left and suffix_if_chopped:
139 chopped += suffix_if_chopped
155 chopped += suffix_if_chopped
140
156
141 return chopped
157 return chopped
142
158
143
159
144 def shorter(text, size=20):
160 def shorter(text, size=20):
145 postfix = '...'
161 postfix = '...'
146 if len(text) > size:
162 if len(text) > size:
147 return text[:size - len(postfix)] + postfix
163 return text[:size - len(postfix)] + postfix
148 return text
164 return text
149
165
150
166
151 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
167 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
152 """
168 """
153 Reset button
169 Reset button
154 """
170 """
155 _set_input_attrs(attrs, type, name, value)
171 _set_input_attrs(attrs, type, name, value)
156 _set_id_attr(attrs, id, name)
172 _set_id_attr(attrs, id, name)
157 convert_boolean_attrs(attrs, ["disabled"])
173 convert_boolean_attrs(attrs, ["disabled"])
158 return HTML.input(**attrs)
174 return HTML.input(**attrs)
159
175
160 reset = _reset
176 reset = _reset
161 safeid = _make_safe_id_component
177 safeid = _make_safe_id_component
162
178
163
179
164 def branding(name, length=40):
180 def branding(name, length=40):
165 return truncate(name, length, indicator="")
181 return truncate(name, length, indicator="")
166
182
167
183
168 def FID(raw_id, path):
184 def FID(raw_id, path):
169 """
185 """
170 Creates a unique ID for filenode based on it's hash of path and commit
186 Creates a unique ID for filenode based on it's hash of path and commit
171 it's safe to use in urls
187 it's safe to use in urls
172
188
173 :param raw_id:
189 :param raw_id:
174 :param path:
190 :param path:
175 """
191 """
176
192
177 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
193 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
178
194
179
195
180 class _GetError(object):
196 class _GetError(object):
181 """Get error from form_errors, and represent it as span wrapped error
197 """Get error from form_errors, and represent it as span wrapped error
182 message
198 message
183
199
184 :param field_name: field to fetch errors for
200 :param field_name: field to fetch errors for
185 :param form_errors: form errors dict
201 :param form_errors: form errors dict
186 """
202 """
187
203
188 def __call__(self, field_name, form_errors):
204 def __call__(self, field_name, form_errors):
189 tmpl = """<span class="error_msg">%s</span>"""
205 tmpl = """<span class="error_msg">%s</span>"""
190 if form_errors and field_name in form_errors:
206 if form_errors and field_name in form_errors:
191 return literal(tmpl % form_errors.get(field_name))
207 return literal(tmpl % form_errors.get(field_name))
192
208
193 get_error = _GetError()
209 get_error = _GetError()
194
210
195
211
196 class _ToolTip(object):
212 class _ToolTip(object):
197
213
198 def __call__(self, tooltip_title, trim_at=50):
214 def __call__(self, tooltip_title, trim_at=50):
199 """
215 """
200 Special function just to wrap our text into nice formatted
216 Special function just to wrap our text into nice formatted
201 autowrapped text
217 autowrapped text
202
218
203 :param tooltip_title:
219 :param tooltip_title:
204 """
220 """
205 tooltip_title = escape(tooltip_title)
221 tooltip_title = escape(tooltip_title)
206 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
222 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
207 return tooltip_title
223 return tooltip_title
208 tooltip = _ToolTip()
224 tooltip = _ToolTip()
209
225
210
226
211 def files_breadcrumbs(repo_name, commit_id, file_path):
227 def files_breadcrumbs(repo_name, commit_id, file_path):
212 if isinstance(file_path, str):
228 if isinstance(file_path, str):
213 file_path = safe_unicode(file_path)
229 file_path = safe_unicode(file_path)
214
230
215 # TODO: johbo: Is this always a url like path, or is this operating
231 # TODO: johbo: Is this always a url like path, or is this operating
216 # system dependent?
232 # system dependent?
217 path_segments = file_path.split('/')
233 path_segments = file_path.split('/')
218
234
219 repo_name_html = escape(repo_name)
235 repo_name_html = escape(repo_name)
220 if len(path_segments) == 1 and path_segments[0] == '':
236 if len(path_segments) == 1 and path_segments[0] == '':
221 url_segments = [repo_name_html]
237 url_segments = [repo_name_html]
222 else:
238 else:
223 url_segments = [
239 url_segments = [
224 link_to(
240 link_to(
225 repo_name_html,
241 repo_name_html,
226 url('files_home',
242 url('files_home',
227 repo_name=repo_name,
243 repo_name=repo_name,
228 revision=commit_id,
244 revision=commit_id,
229 f_path=''),
245 f_path=''),
230 class_='pjax-link')]
246 class_='pjax-link')]
231
247
232 last_cnt = len(path_segments) - 1
248 last_cnt = len(path_segments) - 1
233 for cnt, segment in enumerate(path_segments):
249 for cnt, segment in enumerate(path_segments):
234 if not segment:
250 if not segment:
235 continue
251 continue
236 segment_html = escape(segment)
252 segment_html = escape(segment)
237
253
238 if cnt != last_cnt:
254 if cnt != last_cnt:
239 url_segments.append(
255 url_segments.append(
240 link_to(
256 link_to(
241 segment_html,
257 segment_html,
242 url('files_home',
258 url('files_home',
243 repo_name=repo_name,
259 repo_name=repo_name,
244 revision=commit_id,
260 revision=commit_id,
245 f_path='/'.join(path_segments[:cnt + 1])),
261 f_path='/'.join(path_segments[:cnt + 1])),
246 class_='pjax-link'))
262 class_='pjax-link'))
247 else:
263 else:
248 url_segments.append(segment_html)
264 url_segments.append(segment_html)
249
265
250 return literal('/'.join(url_segments))
266 return literal('/'.join(url_segments))
251
267
252
268
253 class CodeHtmlFormatter(HtmlFormatter):
269 class CodeHtmlFormatter(HtmlFormatter):
254 """
270 """
255 My code Html Formatter for source codes
271 My code Html Formatter for source codes
256 """
272 """
257
273
258 def wrap(self, source, outfile):
274 def wrap(self, source, outfile):
259 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
275 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
260
276
261 def _wrap_code(self, source):
277 def _wrap_code(self, source):
262 for cnt, it in enumerate(source):
278 for cnt, it in enumerate(source):
263 i, t = it
279 i, t = it
264 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
280 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
265 yield i, t
281 yield i, t
266
282
267 def _wrap_tablelinenos(self, inner):
283 def _wrap_tablelinenos(self, inner):
268 dummyoutfile = StringIO.StringIO()
284 dummyoutfile = StringIO.StringIO()
269 lncount = 0
285 lncount = 0
270 for t, line in inner:
286 for t, line in inner:
271 if t:
287 if t:
272 lncount += 1
288 lncount += 1
273 dummyoutfile.write(line)
289 dummyoutfile.write(line)
274
290
275 fl = self.linenostart
291 fl = self.linenostart
276 mw = len(str(lncount + fl - 1))
292 mw = len(str(lncount + fl - 1))
277 sp = self.linenospecial
293 sp = self.linenospecial
278 st = self.linenostep
294 st = self.linenostep
279 la = self.lineanchors
295 la = self.lineanchors
280 aln = self.anchorlinenos
296 aln = self.anchorlinenos
281 nocls = self.noclasses
297 nocls = self.noclasses
282 if sp:
298 if sp:
283 lines = []
299 lines = []
284
300
285 for i in range(fl, fl + lncount):
301 for i in range(fl, fl + lncount):
286 if i % st == 0:
302 if i % st == 0:
287 if i % sp == 0:
303 if i % sp == 0:
288 if aln:
304 if aln:
289 lines.append('<a href="#%s%d" class="special">%*d</a>' %
305 lines.append('<a href="#%s%d" class="special">%*d</a>' %
290 (la, i, mw, i))
306 (la, i, mw, i))
291 else:
307 else:
292 lines.append('<span class="special">%*d</span>' % (mw, i))
308 lines.append('<span class="special">%*d</span>' % (mw, i))
293 else:
309 else:
294 if aln:
310 if aln:
295 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
311 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
296 else:
312 else:
297 lines.append('%*d' % (mw, i))
313 lines.append('%*d' % (mw, i))
298 else:
314 else:
299 lines.append('')
315 lines.append('')
300 ls = '\n'.join(lines)
316 ls = '\n'.join(lines)
301 else:
317 else:
302 lines = []
318 lines = []
303 for i in range(fl, fl + lncount):
319 for i in range(fl, fl + lncount):
304 if i % st == 0:
320 if i % st == 0:
305 if aln:
321 if aln:
306 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
322 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
307 else:
323 else:
308 lines.append('%*d' % (mw, i))
324 lines.append('%*d' % (mw, i))
309 else:
325 else:
310 lines.append('')
326 lines.append('')
311 ls = '\n'.join(lines)
327 ls = '\n'.join(lines)
312
328
313 # in case you wonder about the seemingly redundant <div> here: since the
329 # in case you wonder about the seemingly redundant <div> here: since the
314 # content in the other cell also is wrapped in a div, some browsers in
330 # content in the other cell also is wrapped in a div, some browsers in
315 # some configurations seem to mess up the formatting...
331 # some configurations seem to mess up the formatting...
316 if nocls:
332 if nocls:
317 yield 0, ('<table class="%stable">' % self.cssclass +
333 yield 0, ('<table class="%stable">' % self.cssclass +
318 '<tr><td><div class="linenodiv" '
334 '<tr><td><div class="linenodiv" '
319 'style="background-color: #f0f0f0; padding-right: 10px">'
335 'style="background-color: #f0f0f0; padding-right: 10px">'
320 '<pre style="line-height: 125%">' +
336 '<pre style="line-height: 125%">' +
321 ls + '</pre></div></td><td id="hlcode" class="code">')
337 ls + '</pre></div></td><td id="hlcode" class="code">')
322 else:
338 else:
323 yield 0, ('<table class="%stable">' % self.cssclass +
339 yield 0, ('<table class="%stable">' % self.cssclass +
324 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
340 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
325 ls + '</pre></div></td><td id="hlcode" class="code">')
341 ls + '</pre></div></td><td id="hlcode" class="code">')
326 yield 0, dummyoutfile.getvalue()
342 yield 0, dummyoutfile.getvalue()
327 yield 0, '</td></tr></table>'
343 yield 0, '</td></tr></table>'
328
344
329
345
330 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
346 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
331 def __init__(self, **kw):
347 def __init__(self, **kw):
332 # only show these line numbers if set
348 # only show these line numbers if set
333 self.only_lines = kw.pop('only_line_numbers', [])
349 self.only_lines = kw.pop('only_line_numbers', [])
334 self.query_terms = kw.pop('query_terms', [])
350 self.query_terms = kw.pop('query_terms', [])
335 self.max_lines = kw.pop('max_lines', 5)
351 self.max_lines = kw.pop('max_lines', 5)
336 self.line_context = kw.pop('line_context', 3)
352 self.line_context = kw.pop('line_context', 3)
337 self.url = kw.pop('url', None)
353 self.url = kw.pop('url', None)
338
354
339 super(CodeHtmlFormatter, self).__init__(**kw)
355 super(CodeHtmlFormatter, self).__init__(**kw)
340
356
341 def _wrap_code(self, source):
357 def _wrap_code(self, source):
342 for cnt, it in enumerate(source):
358 for cnt, it in enumerate(source):
343 i, t = it
359 i, t = it
344 t = '<pre>%s</pre>' % t
360 t = '<pre>%s</pre>' % t
345 yield i, t
361 yield i, t
346
362
347 def _wrap_tablelinenos(self, inner):
363 def _wrap_tablelinenos(self, inner):
348 yield 0, '<table class="code-highlight %stable">' % self.cssclass
364 yield 0, '<table class="code-highlight %stable">' % self.cssclass
349
365
350 last_shown_line_number = 0
366 last_shown_line_number = 0
351 current_line_number = 1
367 current_line_number = 1
352
368
353 for t, line in inner:
369 for t, line in inner:
354 if not t:
370 if not t:
355 yield t, line
371 yield t, line
356 continue
372 continue
357
373
358 if current_line_number in self.only_lines:
374 if current_line_number in self.only_lines:
359 if last_shown_line_number + 1 != current_line_number:
375 if last_shown_line_number + 1 != current_line_number:
360 yield 0, '<tr>'
376 yield 0, '<tr>'
361 yield 0, '<td class="line">...</td>'
377 yield 0, '<td class="line">...</td>'
362 yield 0, '<td id="hlcode" class="code"></td>'
378 yield 0, '<td id="hlcode" class="code"></td>'
363 yield 0, '</tr>'
379 yield 0, '</tr>'
364
380
365 yield 0, '<tr>'
381 yield 0, '<tr>'
366 if self.url:
382 if self.url:
367 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
383 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
368 self.url, current_line_number, current_line_number)
384 self.url, current_line_number, current_line_number)
369 else:
385 else:
370 yield 0, '<td class="line"><a href="">%i</a></td>' % (
386 yield 0, '<td class="line"><a href="">%i</a></td>' % (
371 current_line_number)
387 current_line_number)
372 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
388 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
373 yield 0, '</tr>'
389 yield 0, '</tr>'
374
390
375 last_shown_line_number = current_line_number
391 last_shown_line_number = current_line_number
376
392
377 current_line_number += 1
393 current_line_number += 1
378
394
379
395
380 yield 0, '</table>'
396 yield 0, '</table>'
381
397
382
398
383 def extract_phrases(text_query):
399 def extract_phrases(text_query):
384 """
400 """
385 Extracts phrases from search term string making sure phrases
401 Extracts phrases from search term string making sure phrases
386 contained in double quotes are kept together - and discarding empty values
402 contained in double quotes are kept together - and discarding empty values
387 or fully whitespace values eg.
403 or fully whitespace values eg.
388
404
389 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
405 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
390
406
391 """
407 """
392
408
393 in_phrase = False
409 in_phrase = False
394 buf = ''
410 buf = ''
395 phrases = []
411 phrases = []
396 for char in text_query:
412 for char in text_query:
397 if in_phrase:
413 if in_phrase:
398 if char == '"': # end phrase
414 if char == '"': # end phrase
399 phrases.append(buf)
415 phrases.append(buf)
400 buf = ''
416 buf = ''
401 in_phrase = False
417 in_phrase = False
402 continue
418 continue
403 else:
419 else:
404 buf += char
420 buf += char
405 continue
421 continue
406 else:
422 else:
407 if char == '"': # start phrase
423 if char == '"': # start phrase
408 in_phrase = True
424 in_phrase = True
409 phrases.append(buf)
425 phrases.append(buf)
410 buf = ''
426 buf = ''
411 continue
427 continue
412 elif char == ' ':
428 elif char == ' ':
413 phrases.append(buf)
429 phrases.append(buf)
414 buf = ''
430 buf = ''
415 continue
431 continue
416 else:
432 else:
417 buf += char
433 buf += char
418
434
419 phrases.append(buf)
435 phrases.append(buf)
420 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
436 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
421 return phrases
437 return phrases
422
438
423
439
424 def get_matching_offsets(text, phrases):
440 def get_matching_offsets(text, phrases):
425 """
441 """
426 Returns a list of string offsets in `text` that the list of `terms` match
442 Returns a list of string offsets in `text` that the list of `terms` match
427
443
428 >>> get_matching_offsets('some text here', ['some', 'here'])
444 >>> get_matching_offsets('some text here', ['some', 'here'])
429 [(0, 4), (10, 14)]
445 [(0, 4), (10, 14)]
430
446
431 """
447 """
432 offsets = []
448 offsets = []
433 for phrase in phrases:
449 for phrase in phrases:
434 for match in re.finditer(phrase, text):
450 for match in re.finditer(phrase, text):
435 offsets.append((match.start(), match.end()))
451 offsets.append((match.start(), match.end()))
436
452
437 return offsets
453 return offsets
438
454
439
455
440 def normalize_text_for_matching(x):
456 def normalize_text_for_matching(x):
441 """
457 """
442 Replaces all non alnum characters to spaces and lower cases the string,
458 Replaces all non alnum characters to spaces and lower cases the string,
443 useful for comparing two text strings without punctuation
459 useful for comparing two text strings without punctuation
444 """
460 """
445 return re.sub(r'[^\w]', ' ', x.lower())
461 return re.sub(r'[^\w]', ' ', x.lower())
446
462
447
463
448 def get_matching_line_offsets(lines, terms):
464 def get_matching_line_offsets(lines, terms):
449 """ Return a set of `lines` indices (starting from 1) matching a
465 """ Return a set of `lines` indices (starting from 1) matching a
450 text search query, along with `context` lines above/below matching lines
466 text search query, along with `context` lines above/below matching lines
451
467
452 :param lines: list of strings representing lines
468 :param lines: list of strings representing lines
453 :param terms: search term string to match in lines eg. 'some text'
469 :param terms: search term string to match in lines eg. 'some text'
454 :param context: number of lines above/below a matching line to add to result
470 :param context: number of lines above/below a matching line to add to result
455 :param max_lines: cut off for lines of interest
471 :param max_lines: cut off for lines of interest
456 eg.
472 eg.
457
473
458 text = '''
474 text = '''
459 words words words
475 words words words
460 words words words
476 words words words
461 some text some
477 some text some
462 words words words
478 words words words
463 words words words
479 words words words
464 text here what
480 text here what
465 '''
481 '''
466 get_matching_line_offsets(text, 'text', context=1)
482 get_matching_line_offsets(text, 'text', context=1)
467 {3: [(5, 9)], 6: [(0, 4)]]
483 {3: [(5, 9)], 6: [(0, 4)]]
468
484
469 """
485 """
470 matching_lines = {}
486 matching_lines = {}
471 phrases = [normalize_text_for_matching(phrase)
487 phrases = [normalize_text_for_matching(phrase)
472 for phrase in extract_phrases(terms)]
488 for phrase in extract_phrases(terms)]
473
489
474 for line_index, line in enumerate(lines, start=1):
490 for line_index, line in enumerate(lines, start=1):
475 match_offsets = get_matching_offsets(
491 match_offsets = get_matching_offsets(
476 normalize_text_for_matching(line), phrases)
492 normalize_text_for_matching(line), phrases)
477 if match_offsets:
493 if match_offsets:
478 matching_lines[line_index] = match_offsets
494 matching_lines[line_index] = match_offsets
479
495
480 return matching_lines
496 return matching_lines
481
497
482
498
483 def get_lexer_safe(mimetype=None, filepath=None):
499 def get_lexer_safe(mimetype=None, filepath=None):
484 """
500 """
485 Tries to return a relevant pygments lexer using mimetype/filepath name,
501 Tries to return a relevant pygments lexer using mimetype/filepath name,
486 defaulting to plain text if none could be found
502 defaulting to plain text if none could be found
487 """
503 """
488 lexer = None
504 lexer = None
489 try:
505 try:
490 if mimetype:
506 if mimetype:
491 lexer = get_lexer_for_mimetype(mimetype)
507 lexer = get_lexer_for_mimetype(mimetype)
492 if not lexer:
508 if not lexer:
493 lexer = get_lexer_for_filename(filepath)
509 lexer = get_lexer_for_filename(filepath)
494 except pygments.util.ClassNotFound:
510 except pygments.util.ClassNotFound:
495 pass
511 pass
496
512
497 if not lexer:
513 if not lexer:
498 lexer = get_lexer_by_name('text')
514 lexer = get_lexer_by_name('text')
499
515
500 return lexer
516 return lexer
501
517
502
518
503 def pygmentize(filenode, **kwargs):
519 def pygmentize(filenode, **kwargs):
504 """
520 """
505 pygmentize function using pygments
521 pygmentize function using pygments
506
522
507 :param filenode:
523 :param filenode:
508 """
524 """
509 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
525 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
510 return literal(code_highlight(filenode.content, lexer,
526 return literal(code_highlight(filenode.content, lexer,
511 CodeHtmlFormatter(**kwargs)))
527 CodeHtmlFormatter(**kwargs)))
512
528
513
529
514 def pygmentize_annotation(repo_name, filenode, **kwargs):
530 def pygmentize_annotation(repo_name, filenode, **kwargs):
515 """
531 """
516 pygmentize function for annotation
532 pygmentize function for annotation
517
533
518 :param filenode:
534 :param filenode:
519 """
535 """
520
536
521 color_dict = {}
537 color_dict = {}
522
538
523 def gen_color(n=10000):
539 def gen_color(n=10000):
524 """generator for getting n of evenly distributed colors using
540 """generator for getting n of evenly distributed colors using
525 hsv color and golden ratio. It always return same order of colors
541 hsv color and golden ratio. It always return same order of colors
526
542
527 :returns: RGB tuple
543 :returns: RGB tuple
528 """
544 """
529
545
530 def hsv_to_rgb(h, s, v):
546 def hsv_to_rgb(h, s, v):
531 if s == 0.0:
547 if s == 0.0:
532 return v, v, v
548 return v, v, v
533 i = int(h * 6.0) # XXX assume int() truncates!
549 i = int(h * 6.0) # XXX assume int() truncates!
534 f = (h * 6.0) - i
550 f = (h * 6.0) - i
535 p = v * (1.0 - s)
551 p = v * (1.0 - s)
536 q = v * (1.0 - s * f)
552 q = v * (1.0 - s * f)
537 t = v * (1.0 - s * (1.0 - f))
553 t = v * (1.0 - s * (1.0 - f))
538 i = i % 6
554 i = i % 6
539 if i == 0:
555 if i == 0:
540 return v, t, p
556 return v, t, p
541 if i == 1:
557 if i == 1:
542 return q, v, p
558 return q, v, p
543 if i == 2:
559 if i == 2:
544 return p, v, t
560 return p, v, t
545 if i == 3:
561 if i == 3:
546 return p, q, v
562 return p, q, v
547 if i == 4:
563 if i == 4:
548 return t, p, v
564 return t, p, v
549 if i == 5:
565 if i == 5:
550 return v, p, q
566 return v, p, q
551
567
552 golden_ratio = 0.618033988749895
568 golden_ratio = 0.618033988749895
553 h = 0.22717784590367374
569 h = 0.22717784590367374
554
570
555 for _ in xrange(n):
571 for _ in xrange(n):
556 h += golden_ratio
572 h += golden_ratio
557 h %= 1
573 h %= 1
558 HSV_tuple = [h, 0.95, 0.95]
574 HSV_tuple = [h, 0.95, 0.95]
559 RGB_tuple = hsv_to_rgb(*HSV_tuple)
575 RGB_tuple = hsv_to_rgb(*HSV_tuple)
560 yield map(lambda x: str(int(x * 256)), RGB_tuple)
576 yield map(lambda x: str(int(x * 256)), RGB_tuple)
561
577
562 cgenerator = gen_color()
578 cgenerator = gen_color()
563
579
564 def get_color_string(commit_id):
580 def get_color_string(commit_id):
565 if commit_id in color_dict:
581 if commit_id in color_dict:
566 col = color_dict[commit_id]
582 col = color_dict[commit_id]
567 else:
583 else:
568 col = color_dict[commit_id] = cgenerator.next()
584 col = color_dict[commit_id] = cgenerator.next()
569 return "color: rgb(%s)! important;" % (', '.join(col))
585 return "color: rgb(%s)! important;" % (', '.join(col))
570
586
571 def url_func(repo_name):
587 def url_func(repo_name):
572
588
573 def _url_func(commit):
589 def _url_func(commit):
574 author = commit.author
590 author = commit.author
575 date = commit.date
591 date = commit.date
576 message = tooltip(commit.message)
592 message = tooltip(commit.message)
577
593
578 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
594 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
579 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
595 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
580 "</b> %s<br/></div>")
596 "</b> %s<br/></div>")
581
597
582 tooltip_html = tooltip_html % (author, date, message)
598 tooltip_html = tooltip_html % (author, date, message)
583 lnk_format = '%5s:%s' % ('r%s' % commit.idx, commit.short_id)
599 lnk_format = '%5s:%s' % ('r%s' % commit.idx, commit.short_id)
584 uri = link_to(
600 uri = link_to(
585 lnk_format,
601 lnk_format,
586 url('changeset_home', repo_name=repo_name,
602 url('changeset_home', repo_name=repo_name,
587 revision=commit.raw_id),
603 revision=commit.raw_id),
588 style=get_color_string(commit.raw_id),
604 style=get_color_string(commit.raw_id),
589 class_='tooltip',
605 class_='tooltip',
590 title=tooltip_html
606 title=tooltip_html
591 )
607 )
592
608
593 uri += '\n'
609 uri += '\n'
594 return uri
610 return uri
595 return _url_func
611 return _url_func
596
612
597 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
613 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
598
614
599
615
600 def is_following_repo(repo_name, user_id):
616 def is_following_repo(repo_name, user_id):
601 from rhodecode.model.scm import ScmModel
617 from rhodecode.model.scm import ScmModel
602 return ScmModel().is_following_repo(repo_name, user_id)
618 return ScmModel().is_following_repo(repo_name, user_id)
603
619
604
620
605 class _Message(object):
621 class _Message(object):
606 """A message returned by ``Flash.pop_messages()``.
622 """A message returned by ``Flash.pop_messages()``.
607
623
608 Converting the message to a string returns the message text. Instances
624 Converting the message to a string returns the message text. Instances
609 also have the following attributes:
625 also have the following attributes:
610
626
611 * ``message``: the message text.
627 * ``message``: the message text.
612 * ``category``: the category specified when the message was created.
628 * ``category``: the category specified when the message was created.
613 """
629 """
614
630
615 def __init__(self, category, message):
631 def __init__(self, category, message):
616 self.category = category
632 self.category = category
617 self.message = message
633 self.message = message
618
634
619 def __str__(self):
635 def __str__(self):
620 return self.message
636 return self.message
621
637
622 __unicode__ = __str__
638 __unicode__ = __str__
623
639
624 def __html__(self):
640 def __html__(self):
625 return escape(safe_unicode(self.message))
641 return escape(safe_unicode(self.message))
626
642
627
643
628 class Flash(_Flash):
644 class Flash(_Flash):
629
645
630 def pop_messages(self):
646 def pop_messages(self):
631 """Return all accumulated messages and delete them from the session.
647 """Return all accumulated messages and delete them from the session.
632
648
633 The return value is a list of ``Message`` objects.
649 The return value is a list of ``Message`` objects.
634 """
650 """
635 from pylons import session
651 from pylons import session
636
652
637 messages = []
653 messages = []
638
654
639 # Pop the 'old' pylons flash messages. They are tuples of the form
655 # Pop the 'old' pylons flash messages. They are tuples of the form
640 # (category, message)
656 # (category, message)
641 for cat, msg in session.pop(self.session_key, []):
657 for cat, msg in session.pop(self.session_key, []):
642 messages.append(_Message(cat, msg))
658 messages.append(_Message(cat, msg))
643
659
644 # Pop the 'new' pyramid flash messages for each category as list
660 # Pop the 'new' pyramid flash messages for each category as list
645 # of strings.
661 # of strings.
646 for cat in self.categories:
662 for cat in self.categories:
647 for msg in session.pop_flash(queue=cat):
663 for msg in session.pop_flash(queue=cat):
648 messages.append(_Message(cat, msg))
664 messages.append(_Message(cat, msg))
649 # Map messages from the default queue to the 'notice' category.
665 # Map messages from the default queue to the 'notice' category.
650 for msg in session.pop_flash():
666 for msg in session.pop_flash():
651 messages.append(_Message('notice', msg))
667 messages.append(_Message('notice', msg))
652
668
653 session.save()
669 session.save()
654 return messages
670 return messages
655
671
656 flash = Flash()
672 flash = Flash()
657
673
658 #==============================================================================
674 #==============================================================================
659 # SCM FILTERS available via h.
675 # SCM FILTERS available via h.
660 #==============================================================================
676 #==============================================================================
661 from rhodecode.lib.vcs.utils import author_name, author_email
677 from rhodecode.lib.vcs.utils import author_name, author_email
662 from rhodecode.lib.utils2 import credentials_filter, age as _age
678 from rhodecode.lib.utils2 import credentials_filter, age as _age
663 from rhodecode.model.db import User, ChangesetStatus
679 from rhodecode.model.db import User, ChangesetStatus
664
680
665 age = _age
681 age = _age
666 capitalize = lambda x: x.capitalize()
682 capitalize = lambda x: x.capitalize()
667 email = author_email
683 email = author_email
668 short_id = lambda x: x[:12]
684 short_id = lambda x: x[:12]
669 hide_credentials = lambda x: ''.join(credentials_filter(x))
685 hide_credentials = lambda x: ''.join(credentials_filter(x))
670
686
671
687
672 def age_component(datetime_iso, value=None, time_is_local=False):
688 def age_component(datetime_iso, value=None, time_is_local=False):
673 title = value or format_date(datetime_iso)
689 title = value or format_date(datetime_iso)
674
690
675 # detect if we have a timezone info, otherwise, add it
691 # detect if we have a timezone info, otherwise, add it
676 if isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
692 if isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
677 tzinfo = '+00:00'
693 tzinfo = '+00:00'
678
694
679 if time_is_local:
695 if time_is_local:
680 tzinfo = time.strftime("+%H:%M",
696 tzinfo = time.strftime("+%H:%M",
681 time.gmtime(
697 time.gmtime(
682 (datetime.now() - datetime.utcnow()).seconds + 1
698 (datetime.now() - datetime.utcnow()).seconds + 1
683 )
699 )
684 )
700 )
685
701
686 return literal(
702 return literal(
687 '<time class="timeago tooltip" '
703 '<time class="timeago tooltip" '
688 'title="{1}" datetime="{0}{2}">{1}</time>'.format(
704 'title="{1}" datetime="{0}{2}">{1}</time>'.format(
689 datetime_iso, title, tzinfo))
705 datetime_iso, title, tzinfo))
690
706
691
707
692 def _shorten_commit_id(commit_id):
708 def _shorten_commit_id(commit_id):
693 from rhodecode import CONFIG
709 from rhodecode import CONFIG
694 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
710 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
695 return commit_id[:def_len]
711 return commit_id[:def_len]
696
712
697
713
698 def show_id(commit):
714 def show_id(commit):
699 """
715 """
700 Configurable function that shows ID
716 Configurable function that shows ID
701 by default it's r123:fffeeefffeee
717 by default it's r123:fffeeefffeee
702
718
703 :param commit: commit instance
719 :param commit: commit instance
704 """
720 """
705 from rhodecode import CONFIG
721 from rhodecode import CONFIG
706 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
722 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
707
723
708 raw_id = _shorten_commit_id(commit.raw_id)
724 raw_id = _shorten_commit_id(commit.raw_id)
709 if show_idx:
725 if show_idx:
710 return 'r%s:%s' % (commit.idx, raw_id)
726 return 'r%s:%s' % (commit.idx, raw_id)
711 else:
727 else:
712 return '%s' % (raw_id, )
728 return '%s' % (raw_id, )
713
729
714
730
715 def format_date(date):
731 def format_date(date):
716 """
732 """
717 use a standardized formatting for dates used in RhodeCode
733 use a standardized formatting for dates used in RhodeCode
718
734
719 :param date: date/datetime object
735 :param date: date/datetime object
720 :return: formatted date
736 :return: formatted date
721 """
737 """
722
738
723 if date:
739 if date:
724 _fmt = "%a, %d %b %Y %H:%M:%S"
740 _fmt = "%a, %d %b %Y %H:%M:%S"
725 return safe_unicode(date.strftime(_fmt))
741 return safe_unicode(date.strftime(_fmt))
726
742
727 return u""
743 return u""
728
744
729
745
730 class _RepoChecker(object):
746 class _RepoChecker(object):
731
747
732 def __init__(self, backend_alias):
748 def __init__(self, backend_alias):
733 self._backend_alias = backend_alias
749 self._backend_alias = backend_alias
734
750
735 def __call__(self, repository):
751 def __call__(self, repository):
736 if hasattr(repository, 'alias'):
752 if hasattr(repository, 'alias'):
737 _type = repository.alias
753 _type = repository.alias
738 elif hasattr(repository, 'repo_type'):
754 elif hasattr(repository, 'repo_type'):
739 _type = repository.repo_type
755 _type = repository.repo_type
740 else:
756 else:
741 _type = repository
757 _type = repository
742 return _type == self._backend_alias
758 return _type == self._backend_alias
743
759
744 is_git = _RepoChecker('git')
760 is_git = _RepoChecker('git')
745 is_hg = _RepoChecker('hg')
761 is_hg = _RepoChecker('hg')
746 is_svn = _RepoChecker('svn')
762 is_svn = _RepoChecker('svn')
747
763
748
764
749 def get_repo_type_by_name(repo_name):
765 def get_repo_type_by_name(repo_name):
750 repo = Repository.get_by_repo_name(repo_name)
766 repo = Repository.get_by_repo_name(repo_name)
751 return repo.repo_type
767 return repo.repo_type
752
768
753
769
754 def is_svn_without_proxy(repository):
770 def is_svn_without_proxy(repository):
755 from rhodecode import CONFIG
771 from rhodecode import CONFIG
756 if is_svn(repository):
772 if is_svn(repository):
757 if not CONFIG.get('rhodecode_proxy_subversion_http_requests', False):
773 if not CONFIG.get('rhodecode_proxy_subversion_http_requests', False):
758 return True
774 return True
759 return False
775 return False
760
776
761
777
762 def discover_user(author):
778 def discover_user(author):
763 """
779 """
764 Tries to discover RhodeCode User based on the autho string. Author string
780 Tries to discover RhodeCode User based on the autho string. Author string
765 is typically `FirstName LastName <email@address.com>`
781 is typically `FirstName LastName <email@address.com>`
766 """
782 """
767
783
768 # if author is already an instance use it for extraction
784 # if author is already an instance use it for extraction
769 if isinstance(author, User):
785 if isinstance(author, User):
770 return author
786 return author
771
787
772 # Valid email in the attribute passed, see if they're in the system
788 # Valid email in the attribute passed, see if they're in the system
773 _email = author_email(author)
789 _email = author_email(author)
774 if _email != '':
790 if _email != '':
775 user = User.get_by_email(_email, case_insensitive=True, cache=True)
791 user = User.get_by_email(_email, case_insensitive=True, cache=True)
776 if user is not None:
792 if user is not None:
777 return user
793 return user
778
794
779 # Maybe it's a username, we try to extract it and fetch by username ?
795 # Maybe it's a username, we try to extract it and fetch by username ?
780 _author = author_name(author)
796 _author = author_name(author)
781 user = User.get_by_username(_author, case_insensitive=True, cache=True)
797 user = User.get_by_username(_author, case_insensitive=True, cache=True)
782 if user is not None:
798 if user is not None:
783 return user
799 return user
784
800
785 return None
801 return None
786
802
787
803
788 def email_or_none(author):
804 def email_or_none(author):
789 # extract email from the commit string
805 # extract email from the commit string
790 _email = author_email(author)
806 _email = author_email(author)
791
807
792 # If we have an email, use it, otherwise
808 # If we have an email, use it, otherwise
793 # see if it contains a username we can get an email from
809 # see if it contains a username we can get an email from
794 if _email != '':
810 if _email != '':
795 return _email
811 return _email
796 else:
812 else:
797 user = User.get_by_username(
813 user = User.get_by_username(
798 author_name(author), case_insensitive=True, cache=True)
814 author_name(author), case_insensitive=True, cache=True)
799
815
800 if user is not None:
816 if user is not None:
801 return user.email
817 return user.email
802
818
803 # No valid email, not a valid user in the system, none!
819 # No valid email, not a valid user in the system, none!
804 return None
820 return None
805
821
806
822
807 def link_to_user(author, length=0, **kwargs):
823 def link_to_user(author, length=0, **kwargs):
808 user = discover_user(author)
824 user = discover_user(author)
809 # user can be None, but if we have it already it means we can re-use it
825 # user can be None, but if we have it already it means we can re-use it
810 # in the person() function, so we save 1 intensive-query
826 # in the person() function, so we save 1 intensive-query
811 if user:
827 if user:
812 author = user
828 author = user
813
829
814 display_person = person(author, 'username_or_name_or_email')
830 display_person = person(author, 'username_or_name_or_email')
815 if length:
831 if length:
816 display_person = shorter(display_person, length)
832 display_person = shorter(display_person, length)
817
833
818 if user:
834 if user:
819 return link_to(
835 return link_to(
820 escape(display_person),
836 escape(display_person),
821 url('user_profile', username=user.username),
837 url('user_profile', username=user.username),
822 **kwargs)
838 **kwargs)
823 else:
839 else:
824 return escape(display_person)
840 return escape(display_person)
825
841
826
842
827 def person(author, show_attr="username_and_name"):
843 def person(author, show_attr="username_and_name"):
828 user = discover_user(author)
844 user = discover_user(author)
829 if user:
845 if user:
830 return getattr(user, show_attr)
846 return getattr(user, show_attr)
831 else:
847 else:
832 _author = author_name(author)
848 _author = author_name(author)
833 _email = email(author)
849 _email = email(author)
834 return _author or _email
850 return _author or _email
835
851
836
852
837 def author_string(email):
853 def author_string(email):
838 if email:
854 if email:
839 user = User.get_by_email(email, case_insensitive=True, cache=True)
855 user = User.get_by_email(email, case_insensitive=True, cache=True)
840 if user:
856 if user:
841 if user.firstname or user.lastname:
857 if user.firstname or user.lastname:
842 return '%s %s &lt;%s&gt;' % (user.firstname, user.lastname, email)
858 return '%s %s &lt;%s&gt;' % (user.firstname, user.lastname, email)
843 else:
859 else:
844 return email
860 return email
845 else:
861 else:
846 return email
862 return email
847 else:
863 else:
848 return None
864 return None
849
865
850
866
851 def person_by_id(id_, show_attr="username_and_name"):
867 def person_by_id(id_, show_attr="username_and_name"):
852 # attr to return from fetched user
868 # attr to return from fetched user
853 person_getter = lambda usr: getattr(usr, show_attr)
869 person_getter = lambda usr: getattr(usr, show_attr)
854
870
855 #maybe it's an ID ?
871 #maybe it's an ID ?
856 if str(id_).isdigit() or isinstance(id_, int):
872 if str(id_).isdigit() or isinstance(id_, int):
857 id_ = int(id_)
873 id_ = int(id_)
858 user = User.get(id_)
874 user = User.get(id_)
859 if user is not None:
875 if user is not None:
860 return person_getter(user)
876 return person_getter(user)
861 return id_
877 return id_
862
878
863
879
864 def gravatar_with_user(author, show_disabled=False):
880 def gravatar_with_user(author, show_disabled=False):
865 from rhodecode.lib.utils import PartialRenderer
881 from rhodecode.lib.utils import PartialRenderer
866 _render = PartialRenderer('base/base.html')
882 _render = PartialRenderer('base/base.html')
867 return _render('gravatar_with_user', author, show_disabled=show_disabled)
883 return _render('gravatar_with_user', author, show_disabled=show_disabled)
868
884
869
885
870 def desc_stylize(value):
886 def desc_stylize(value):
871 """
887 """
872 converts tags from value into html equivalent
888 converts tags from value into html equivalent
873
889
874 :param value:
890 :param value:
875 """
891 """
876 if not value:
892 if not value:
877 return ''
893 return ''
878
894
879 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
895 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
880 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
896 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
881 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
897 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
882 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
898 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
883 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z0-9\-\/]*)\]',
899 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z0-9\-\/]*)\]',
884 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
900 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
885 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]',
901 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]',
886 '<div class="metatag" tag="lang">\\2</div>', value)
902 '<div class="metatag" tag="lang">\\2</div>', value)
887 value = re.sub(r'\[([a-z]+)\]',
903 value = re.sub(r'\[([a-z]+)\]',
888 '<div class="metatag" tag="\\1">\\1</div>', value)
904 '<div class="metatag" tag="\\1">\\1</div>', value)
889
905
890 return value
906 return value
891
907
892
908
893 def escaped_stylize(value):
909 def escaped_stylize(value):
894 """
910 """
895 converts tags from value into html equivalent, but escaping its value first
911 converts tags from value into html equivalent, but escaping its value first
896 """
912 """
897 if not value:
913 if not value:
898 return ''
914 return ''
899
915
900 # Using default webhelper escape method, but has to force it as a
916 # Using default webhelper escape method, but has to force it as a
901 # plain unicode instead of a markup tag to be used in regex expressions
917 # plain unicode instead of a markup tag to be used in regex expressions
902 value = unicode(escape(safe_unicode(value)))
918 value = unicode(escape(safe_unicode(value)))
903
919
904 value = re.sub(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
920 value = re.sub(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
905 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
921 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
906 value = re.sub(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
922 value = re.sub(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
907 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
923 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
908 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]',
924 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]',
909 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
925 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
910 value = re.sub(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+]*)\]',
926 value = re.sub(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+]*)\]',
911 '<div class="metatag" tag="lang">\\2</div>', value)
927 '<div class="metatag" tag="lang">\\2</div>', value)
912 value = re.sub(r'\[([a-z]+)\]',
928 value = re.sub(r'\[([a-z]+)\]',
913 '<div class="metatag" tag="\\1">\\1</div>', value)
929 '<div class="metatag" tag="\\1">\\1</div>', value)
914
930
915 return value
931 return value
916
932
917
933
918 def bool2icon(value):
934 def bool2icon(value):
919 """
935 """
920 Returns boolean value of a given value, represented as html element with
936 Returns boolean value of a given value, represented as html element with
921 classes that will represent icons
937 classes that will represent icons
922
938
923 :param value: given value to convert to html node
939 :param value: given value to convert to html node
924 """
940 """
925
941
926 if value: # does bool conversion
942 if value: # does bool conversion
927 return HTML.tag('i', class_="icon-true")
943 return HTML.tag('i', class_="icon-true")
928 else: # not true as bool
944 else: # not true as bool
929 return HTML.tag('i', class_="icon-false")
945 return HTML.tag('i', class_="icon-false")
930
946
931
947
932 #==============================================================================
948 #==============================================================================
933 # PERMS
949 # PERMS
934 #==============================================================================
950 #==============================================================================
935 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
951 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
936 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
952 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
937 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token
953 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token
938
954
939
955
940 #==============================================================================
956 #==============================================================================
941 # GRAVATAR URL
957 # GRAVATAR URL
942 #==============================================================================
958 #==============================================================================
943 class InitialsGravatar(object):
959 class InitialsGravatar(object):
944 def __init__(self, email_address, first_name, last_name, size=30,
960 def __init__(self, email_address, first_name, last_name, size=30,
945 background=None, text_color='#fff'):
961 background=None, text_color='#fff'):
946 self.size = size
962 self.size = size
947 self.first_name = first_name
963 self.first_name = first_name
948 self.last_name = last_name
964 self.last_name = last_name
949 self.email_address = email_address
965 self.email_address = email_address
950 self.background = background or self.str2color(email_address)
966 self.background = background or self.str2color(email_address)
951 self.text_color = text_color
967 self.text_color = text_color
952
968
953 def get_color_bank(self):
969 def get_color_bank(self):
954 """
970 """
955 returns a predefined list of colors that gravatars can use.
971 returns a predefined list of colors that gravatars can use.
956 Those are randomized distinct colors that guarantee readability and
972 Those are randomized distinct colors that guarantee readability and
957 uniqueness.
973 uniqueness.
958
974
959 generated with: http://phrogz.net/css/distinct-colors.html
975 generated with: http://phrogz.net/css/distinct-colors.html
960 """
976 """
961 return [
977 return [
962 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
978 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
963 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
979 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
964 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
980 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
965 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
981 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
966 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
982 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
967 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
983 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
968 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
984 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
969 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
985 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
970 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
986 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
971 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
987 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
972 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
988 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
973 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
989 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
974 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
990 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
975 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
991 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
976 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
992 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
977 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
993 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
978 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
994 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
979 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
995 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
980 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
996 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
981 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
997 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
982 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
998 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
983 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
999 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
984 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1000 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
985 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1001 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
986 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1002 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
987 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1003 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
988 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1004 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
989 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1005 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
990 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1006 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
991 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1007 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
992 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1008 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
993 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1009 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
994 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1010 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
995 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1011 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
996 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1012 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
997 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1013 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
998 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1014 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
999 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1015 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1000 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1016 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1001 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1017 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1002 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1018 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1003 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1019 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1004 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1020 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1005 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1021 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1006 '#4f8c46', '#368dd9', '#5c0073'
1022 '#4f8c46', '#368dd9', '#5c0073'
1007 ]
1023 ]
1008
1024
1009 def rgb_to_hex_color(self, rgb_tuple):
1025 def rgb_to_hex_color(self, rgb_tuple):
1010 """
1026 """
1011 Converts an rgb_tuple passed to an hex color.
1027 Converts an rgb_tuple passed to an hex color.
1012
1028
1013 :param rgb_tuple: tuple with 3 ints represents rgb color space
1029 :param rgb_tuple: tuple with 3 ints represents rgb color space
1014 """
1030 """
1015 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1031 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1016
1032
1017 def email_to_int_list(self, email_str):
1033 def email_to_int_list(self, email_str):
1018 """
1034 """
1019 Get every byte of the hex digest value of email and turn it to integer.
1035 Get every byte of the hex digest value of email and turn it to integer.
1020 It's going to be always between 0-255
1036 It's going to be always between 0-255
1021 """
1037 """
1022 digest = md5_safe(email_str.lower())
1038 digest = md5_safe(email_str.lower())
1023 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1039 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1024
1040
1025 def pick_color_bank_index(self, email_str, color_bank):
1041 def pick_color_bank_index(self, email_str, color_bank):
1026 return self.email_to_int_list(email_str)[0] % len(color_bank)
1042 return self.email_to_int_list(email_str)[0] % len(color_bank)
1027
1043
1028 def str2color(self, email_str):
1044 def str2color(self, email_str):
1029 """
1045 """
1030 Tries to map in a stable algorithm an email to color
1046 Tries to map in a stable algorithm an email to color
1031
1047
1032 :param email_str:
1048 :param email_str:
1033 """
1049 """
1034 color_bank = self.get_color_bank()
1050 color_bank = self.get_color_bank()
1035 # pick position (module it's length so we always find it in the
1051 # pick position (module it's length so we always find it in the
1036 # bank even if it's smaller than 256 values
1052 # bank even if it's smaller than 256 values
1037 pos = self.pick_color_bank_index(email_str, color_bank)
1053 pos = self.pick_color_bank_index(email_str, color_bank)
1038 return color_bank[pos]
1054 return color_bank[pos]
1039
1055
1040 def normalize_email(self, email_address):
1056 def normalize_email(self, email_address):
1041 import unicodedata
1057 import unicodedata
1042 # default host used to fill in the fake/missing email
1058 # default host used to fill in the fake/missing email
1043 default_host = u'localhost'
1059 default_host = u'localhost'
1044
1060
1045 if not email_address:
1061 if not email_address:
1046 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1062 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1047
1063
1048 email_address = safe_unicode(email_address)
1064 email_address = safe_unicode(email_address)
1049
1065
1050 if u'@' not in email_address:
1066 if u'@' not in email_address:
1051 email_address = u'%s@%s' % (email_address, default_host)
1067 email_address = u'%s@%s' % (email_address, default_host)
1052
1068
1053 if email_address.endswith(u'@'):
1069 if email_address.endswith(u'@'):
1054 email_address = u'%s%s' % (email_address, default_host)
1070 email_address = u'%s%s' % (email_address, default_host)
1055
1071
1056 email_address = unicodedata.normalize('NFKD', email_address)\
1072 email_address = unicodedata.normalize('NFKD', email_address)\
1057 .encode('ascii', 'ignore')
1073 .encode('ascii', 'ignore')
1058 return email_address
1074 return email_address
1059
1075
1060 def get_initials(self):
1076 def get_initials(self):
1061 """
1077 """
1062 Returns 2 letter initials calculated based on the input.
1078 Returns 2 letter initials calculated based on the input.
1063 The algorithm picks first given email address, and takes first letter
1079 The algorithm picks first given email address, and takes first letter
1064 of part before @, and then the first letter of server name. In case
1080 of part before @, and then the first letter of server name. In case
1065 the part before @ is in a format of `somestring.somestring2` it replaces
1081 the part before @ is in a format of `somestring.somestring2` it replaces
1066 the server letter with first letter of somestring2
1082 the server letter with first letter of somestring2
1067
1083
1068 In case function was initialized with both first and lastname, this
1084 In case function was initialized with both first and lastname, this
1069 overrides the extraction from email by first letter of the first and
1085 overrides the extraction from email by first letter of the first and
1070 last name. We add special logic to that functionality, In case Full name
1086 last name. We add special logic to that functionality, In case Full name
1071 is compound, like Guido Von Rossum, we use last part of the last name
1087 is compound, like Guido Von Rossum, we use last part of the last name
1072 (Von Rossum) picking `R`.
1088 (Von Rossum) picking `R`.
1073
1089
1074 Function also normalizes the non-ascii characters to they ascii
1090 Function also normalizes the non-ascii characters to they ascii
1075 representation, eg Δ„ => A
1091 representation, eg Δ„ => A
1076 """
1092 """
1077 import unicodedata
1093 import unicodedata
1078 # replace non-ascii to ascii
1094 # replace non-ascii to ascii
1079 first_name = unicodedata.normalize(
1095 first_name = unicodedata.normalize(
1080 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1096 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1081 last_name = unicodedata.normalize(
1097 last_name = unicodedata.normalize(
1082 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1098 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1083
1099
1084 # do NFKD encoding, and also make sure email has proper format
1100 # do NFKD encoding, and also make sure email has proper format
1085 email_address = self.normalize_email(self.email_address)
1101 email_address = self.normalize_email(self.email_address)
1086
1102
1087 # first push the email initials
1103 # first push the email initials
1088 prefix, server = email_address.split('@', 1)
1104 prefix, server = email_address.split('@', 1)
1089
1105
1090 # check if prefix is maybe a 'firstname.lastname' syntax
1106 # check if prefix is maybe a 'firstname.lastname' syntax
1091 _dot_split = prefix.rsplit('.', 1)
1107 _dot_split = prefix.rsplit('.', 1)
1092 if len(_dot_split) == 2:
1108 if len(_dot_split) == 2:
1093 initials = [_dot_split[0][0], _dot_split[1][0]]
1109 initials = [_dot_split[0][0], _dot_split[1][0]]
1094 else:
1110 else:
1095 initials = [prefix[0], server[0]]
1111 initials = [prefix[0], server[0]]
1096
1112
1097 # then try to replace either firtname or lastname
1113 # then try to replace either firtname or lastname
1098 fn_letter = (first_name or " ")[0].strip()
1114 fn_letter = (first_name or " ")[0].strip()
1099 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1115 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1100
1116
1101 if fn_letter:
1117 if fn_letter:
1102 initials[0] = fn_letter
1118 initials[0] = fn_letter
1103
1119
1104 if ln_letter:
1120 if ln_letter:
1105 initials[1] = ln_letter
1121 initials[1] = ln_letter
1106
1122
1107 return ''.join(initials).upper()
1123 return ''.join(initials).upper()
1108
1124
1109 def get_img_data_by_type(self, font_family, img_type):
1125 def get_img_data_by_type(self, font_family, img_type):
1110 default_user = """
1126 default_user = """
1111 <svg xmlns="http://www.w3.org/2000/svg"
1127 <svg xmlns="http://www.w3.org/2000/svg"
1112 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1128 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1113 viewBox="-15 -10 439.165 429.164"
1129 viewBox="-15 -10 439.165 429.164"
1114
1130
1115 xml:space="preserve"
1131 xml:space="preserve"
1116 style="background:{background};" >
1132 style="background:{background};" >
1117
1133
1118 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1134 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1119 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1135 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1120 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1136 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1121 168.596,153.916,216.671,
1137 168.596,153.916,216.671,
1122 204.583,216.671z" fill="{text_color}"/>
1138 204.583,216.671z" fill="{text_color}"/>
1123 <path d="M407.164,374.717L360.88,
1139 <path d="M407.164,374.717L360.88,
1124 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1140 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1125 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1141 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1126 15.366-44.203,23.488-69.076,23.488c-24.877,
1142 15.366-44.203,23.488-69.076,23.488c-24.877,
1127 0-48.762-8.122-69.078-23.488
1143 0-48.762-8.122-69.078-23.488
1128 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1144 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1129 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1145 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1130 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1146 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1131 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1147 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1132 19.402-10.527 C409.699,390.129,
1148 19.402-10.527 C409.699,390.129,
1133 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1149 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1134 </svg>""".format(
1150 </svg>""".format(
1135 size=self.size,
1151 size=self.size,
1136 background='#979797', # @grey4
1152 background='#979797', # @grey4
1137 text_color=self.text_color,
1153 text_color=self.text_color,
1138 font_family=font_family)
1154 font_family=font_family)
1139
1155
1140 return {
1156 return {
1141 "default_user": default_user
1157 "default_user": default_user
1142 }[img_type]
1158 }[img_type]
1143
1159
1144 def get_img_data(self, svg_type=None):
1160 def get_img_data(self, svg_type=None):
1145 """
1161 """
1146 generates the svg metadata for image
1162 generates the svg metadata for image
1147 """
1163 """
1148
1164
1149 font_family = ','.join([
1165 font_family = ','.join([
1150 'proximanovaregular',
1166 'proximanovaregular',
1151 'Proxima Nova Regular',
1167 'Proxima Nova Regular',
1152 'Proxima Nova',
1168 'Proxima Nova',
1153 'Arial',
1169 'Arial',
1154 'Lucida Grande',
1170 'Lucida Grande',
1155 'sans-serif'
1171 'sans-serif'
1156 ])
1172 ])
1157 if svg_type:
1173 if svg_type:
1158 return self.get_img_data_by_type(font_family, svg_type)
1174 return self.get_img_data_by_type(font_family, svg_type)
1159
1175
1160 initials = self.get_initials()
1176 initials = self.get_initials()
1161 img_data = """
1177 img_data = """
1162 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1178 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1163 width="{size}" height="{size}"
1179 width="{size}" height="{size}"
1164 style="width: 100%; height: 100%; background-color: {background}"
1180 style="width: 100%; height: 100%; background-color: {background}"
1165 viewBox="0 0 {size} {size}">
1181 viewBox="0 0 {size} {size}">
1166 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1182 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1167 pointer-events="auto" fill="{text_color}"
1183 pointer-events="auto" fill="{text_color}"
1168 font-family="{font_family}"
1184 font-family="{font_family}"
1169 style="font-weight: 400; font-size: {f_size}px;">{text}
1185 style="font-weight: 400; font-size: {f_size}px;">{text}
1170 </text>
1186 </text>
1171 </svg>""".format(
1187 </svg>""".format(
1172 size=self.size,
1188 size=self.size,
1173 f_size=self.size/1.85, # scale the text inside the box nicely
1189 f_size=self.size/1.85, # scale the text inside the box nicely
1174 background=self.background,
1190 background=self.background,
1175 text_color=self.text_color,
1191 text_color=self.text_color,
1176 text=initials.upper(),
1192 text=initials.upper(),
1177 font_family=font_family)
1193 font_family=font_family)
1178
1194
1179 return img_data
1195 return img_data
1180
1196
1181 def generate_svg(self, svg_type=None):
1197 def generate_svg(self, svg_type=None):
1182 img_data = self.get_img_data(svg_type)
1198 img_data = self.get_img_data(svg_type)
1183 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1199 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1184
1200
1185
1201
1186 def initials_gravatar(email_address, first_name, last_name, size=30):
1202 def initials_gravatar(email_address, first_name, last_name, size=30):
1187 svg_type = None
1203 svg_type = None
1188 if email_address == User.DEFAULT_USER_EMAIL:
1204 if email_address == User.DEFAULT_USER_EMAIL:
1189 svg_type = 'default_user'
1205 svg_type = 'default_user'
1190 klass = InitialsGravatar(email_address, first_name, last_name, size)
1206 klass = InitialsGravatar(email_address, first_name, last_name, size)
1191 return klass.generate_svg(svg_type=svg_type)
1207 return klass.generate_svg(svg_type=svg_type)
1192
1208
1193
1209
1194 def gravatar_url(email_address, size=30):
1210 def gravatar_url(email_address, size=30):
1195 # doh, we need to re-import those to mock it later
1211 # doh, we need to re-import those to mock it later
1196 from pylons import tmpl_context as c
1212 from pylons import tmpl_context as c
1197
1213
1198 _use_gravatar = c.visual.use_gravatar
1214 _use_gravatar = c.visual.use_gravatar
1199 _gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL
1215 _gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL
1200
1216
1201 email_address = email_address or User.DEFAULT_USER_EMAIL
1217 email_address = email_address or User.DEFAULT_USER_EMAIL
1202 if isinstance(email_address, unicode):
1218 if isinstance(email_address, unicode):
1203 # hashlib crashes on unicode items
1219 # hashlib crashes on unicode items
1204 email_address = safe_str(email_address)
1220 email_address = safe_str(email_address)
1205
1221
1206 # empty email or default user
1222 # empty email or default user
1207 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1223 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1208 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1224 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1209
1225
1210 if _use_gravatar:
1226 if _use_gravatar:
1211 # TODO: Disuse pyramid thread locals. Think about another solution to
1227 # TODO: Disuse pyramid thread locals. Think about another solution to
1212 # get the host and schema here.
1228 # get the host and schema here.
1213 request = get_current_request()
1229 request = get_current_request()
1214 tmpl = safe_str(_gravatar_url)
1230 tmpl = safe_str(_gravatar_url)
1215 tmpl = tmpl.replace('{email}', email_address)\
1231 tmpl = tmpl.replace('{email}', email_address)\
1216 .replace('{md5email}', md5_safe(email_address.lower())) \
1232 .replace('{md5email}', md5_safe(email_address.lower())) \
1217 .replace('{netloc}', request.host)\
1233 .replace('{netloc}', request.host)\
1218 .replace('{scheme}', request.scheme)\
1234 .replace('{scheme}', request.scheme)\
1219 .replace('{size}', safe_str(size))
1235 .replace('{size}', safe_str(size))
1220 return tmpl
1236 return tmpl
1221 else:
1237 else:
1222 return initials_gravatar(email_address, '', '', size=size)
1238 return initials_gravatar(email_address, '', '', size=size)
1223
1239
1224
1240
1225 class Page(_Page):
1241 class Page(_Page):
1226 """
1242 """
1227 Custom pager to match rendering style with paginator
1243 Custom pager to match rendering style with paginator
1228 """
1244 """
1229
1245
1230 def _get_pos(self, cur_page, max_page, items):
1246 def _get_pos(self, cur_page, max_page, items):
1231 edge = (items / 2) + 1
1247 edge = (items / 2) + 1
1232 if (cur_page <= edge):
1248 if (cur_page <= edge):
1233 radius = max(items / 2, items - cur_page)
1249 radius = max(items / 2, items - cur_page)
1234 elif (max_page - cur_page) < edge:
1250 elif (max_page - cur_page) < edge:
1235 radius = (items - 1) - (max_page - cur_page)
1251 radius = (items - 1) - (max_page - cur_page)
1236 else:
1252 else:
1237 radius = items / 2
1253 radius = items / 2
1238
1254
1239 left = max(1, (cur_page - (radius)))
1255 left = max(1, (cur_page - (radius)))
1240 right = min(max_page, cur_page + (radius))
1256 right = min(max_page, cur_page + (radius))
1241 return left, cur_page, right
1257 return left, cur_page, right
1242
1258
1243 def _range(self, regexp_match):
1259 def _range(self, regexp_match):
1244 """
1260 """
1245 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1261 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1246
1262
1247 Arguments:
1263 Arguments:
1248
1264
1249 regexp_match
1265 regexp_match
1250 A "re" (regular expressions) match object containing the
1266 A "re" (regular expressions) match object containing the
1251 radius of linked pages around the current page in
1267 radius of linked pages around the current page in
1252 regexp_match.group(1) as a string
1268 regexp_match.group(1) as a string
1253
1269
1254 This function is supposed to be called as a callable in
1270 This function is supposed to be called as a callable in
1255 re.sub.
1271 re.sub.
1256
1272
1257 """
1273 """
1258 radius = int(regexp_match.group(1))
1274 radius = int(regexp_match.group(1))
1259
1275
1260 # Compute the first and last page number within the radius
1276 # Compute the first and last page number within the radius
1261 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1277 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1262 # -> leftmost_page = 5
1278 # -> leftmost_page = 5
1263 # -> rightmost_page = 9
1279 # -> rightmost_page = 9
1264 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1280 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1265 self.last_page,
1281 self.last_page,
1266 (radius * 2) + 1)
1282 (radius * 2) + 1)
1267 nav_items = []
1283 nav_items = []
1268
1284
1269 # Create a link to the first page (unless we are on the first page
1285 # Create a link to the first page (unless we are on the first page
1270 # or there would be no need to insert '..' spacers)
1286 # or there would be no need to insert '..' spacers)
1271 if self.page != self.first_page and self.first_page < leftmost_page:
1287 if self.page != self.first_page and self.first_page < leftmost_page:
1272 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1288 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1273
1289
1274 # Insert dots if there are pages between the first page
1290 # Insert dots if there are pages between the first page
1275 # and the currently displayed page range
1291 # and the currently displayed page range
1276 if leftmost_page - self.first_page > 1:
1292 if leftmost_page - self.first_page > 1:
1277 # Wrap in a SPAN tag if nolink_attr is set
1293 # Wrap in a SPAN tag if nolink_attr is set
1278 text = '..'
1294 text = '..'
1279 if self.dotdot_attr:
1295 if self.dotdot_attr:
1280 text = HTML.span(c=text, **self.dotdot_attr)
1296 text = HTML.span(c=text, **self.dotdot_attr)
1281 nav_items.append(text)
1297 nav_items.append(text)
1282
1298
1283 for thispage in xrange(leftmost_page, rightmost_page + 1):
1299 for thispage in xrange(leftmost_page, rightmost_page + 1):
1284 # Hilight the current page number and do not use a link
1300 # Hilight the current page number and do not use a link
1285 if thispage == self.page:
1301 if thispage == self.page:
1286 text = '%s' % (thispage,)
1302 text = '%s' % (thispage,)
1287 # Wrap in a SPAN tag if nolink_attr is set
1303 # Wrap in a SPAN tag if nolink_attr is set
1288 if self.curpage_attr:
1304 if self.curpage_attr:
1289 text = HTML.span(c=text, **self.curpage_attr)
1305 text = HTML.span(c=text, **self.curpage_attr)
1290 nav_items.append(text)
1306 nav_items.append(text)
1291 # Otherwise create just a link to that page
1307 # Otherwise create just a link to that page
1292 else:
1308 else:
1293 text = '%s' % (thispage,)
1309 text = '%s' % (thispage,)
1294 nav_items.append(self._pagerlink(thispage, text))
1310 nav_items.append(self._pagerlink(thispage, text))
1295
1311
1296 # Insert dots if there are pages between the displayed
1312 # Insert dots if there are pages between the displayed
1297 # page numbers and the end of the page range
1313 # page numbers and the end of the page range
1298 if self.last_page - rightmost_page > 1:
1314 if self.last_page - rightmost_page > 1:
1299 text = '..'
1315 text = '..'
1300 # Wrap in a SPAN tag if nolink_attr is set
1316 # Wrap in a SPAN tag if nolink_attr is set
1301 if self.dotdot_attr:
1317 if self.dotdot_attr:
1302 text = HTML.span(c=text, **self.dotdot_attr)
1318 text = HTML.span(c=text, **self.dotdot_attr)
1303 nav_items.append(text)
1319 nav_items.append(text)
1304
1320
1305 # Create a link to the very last page (unless we are on the last
1321 # Create a link to the very last page (unless we are on the last
1306 # page or there would be no need to insert '..' spacers)
1322 # page or there would be no need to insert '..' spacers)
1307 if self.page != self.last_page and rightmost_page < self.last_page:
1323 if self.page != self.last_page and rightmost_page < self.last_page:
1308 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1324 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1309
1325
1310 ## prerender links
1326 ## prerender links
1311 #_page_link = url.current()
1327 #_page_link = url.current()
1312 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1328 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1313 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1329 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1314 return self.separator.join(nav_items)
1330 return self.separator.join(nav_items)
1315
1331
1316 def pager(self, format='~2~', page_param='page', partial_param='partial',
1332 def pager(self, format='~2~', page_param='page', partial_param='partial',
1317 show_if_single_page=False, separator=' ', onclick=None,
1333 show_if_single_page=False, separator=' ', onclick=None,
1318 symbol_first='<<', symbol_last='>>',
1334 symbol_first='<<', symbol_last='>>',
1319 symbol_previous='<', symbol_next='>',
1335 symbol_previous='<', symbol_next='>',
1320 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1336 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1321 curpage_attr={'class': 'pager_curpage'},
1337 curpage_attr={'class': 'pager_curpage'},
1322 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1338 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1323
1339
1324 self.curpage_attr = curpage_attr
1340 self.curpage_attr = curpage_attr
1325 self.separator = separator
1341 self.separator = separator
1326 self.pager_kwargs = kwargs
1342 self.pager_kwargs = kwargs
1327 self.page_param = page_param
1343 self.page_param = page_param
1328 self.partial_param = partial_param
1344 self.partial_param = partial_param
1329 self.onclick = onclick
1345 self.onclick = onclick
1330 self.link_attr = link_attr
1346 self.link_attr = link_attr
1331 self.dotdot_attr = dotdot_attr
1347 self.dotdot_attr = dotdot_attr
1332
1348
1333 # Don't show navigator if there is no more than one page
1349 # Don't show navigator if there is no more than one page
1334 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1350 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1335 return ''
1351 return ''
1336
1352
1337 from string import Template
1353 from string import Template
1338 # Replace ~...~ in token format by range of pages
1354 # Replace ~...~ in token format by range of pages
1339 result = re.sub(r'~(\d+)~', self._range, format)
1355 result = re.sub(r'~(\d+)~', self._range, format)
1340
1356
1341 # Interpolate '%' variables
1357 # Interpolate '%' variables
1342 result = Template(result).safe_substitute({
1358 result = Template(result).safe_substitute({
1343 'first_page': self.first_page,
1359 'first_page': self.first_page,
1344 'last_page': self.last_page,
1360 'last_page': self.last_page,
1345 'page': self.page,
1361 'page': self.page,
1346 'page_count': self.page_count,
1362 'page_count': self.page_count,
1347 'items_per_page': self.items_per_page,
1363 'items_per_page': self.items_per_page,
1348 'first_item': self.first_item,
1364 'first_item': self.first_item,
1349 'last_item': self.last_item,
1365 'last_item': self.last_item,
1350 'item_count': self.item_count,
1366 'item_count': self.item_count,
1351 'link_first': self.page > self.first_page and \
1367 'link_first': self.page > self.first_page and \
1352 self._pagerlink(self.first_page, symbol_first) or '',
1368 self._pagerlink(self.first_page, symbol_first) or '',
1353 'link_last': self.page < self.last_page and \
1369 'link_last': self.page < self.last_page and \
1354 self._pagerlink(self.last_page, symbol_last) or '',
1370 self._pagerlink(self.last_page, symbol_last) or '',
1355 'link_previous': self.previous_page and \
1371 'link_previous': self.previous_page and \
1356 self._pagerlink(self.previous_page, symbol_previous) \
1372 self._pagerlink(self.previous_page, symbol_previous) \
1357 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1373 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1358 'link_next': self.next_page and \
1374 'link_next': self.next_page and \
1359 self._pagerlink(self.next_page, symbol_next) \
1375 self._pagerlink(self.next_page, symbol_next) \
1360 or HTML.span(symbol_next, class_="pg-next disabled")
1376 or HTML.span(symbol_next, class_="pg-next disabled")
1361 })
1377 })
1362
1378
1363 return literal(result)
1379 return literal(result)
1364
1380
1365
1381
1366 #==============================================================================
1382 #==============================================================================
1367 # REPO PAGER, PAGER FOR REPOSITORY
1383 # REPO PAGER, PAGER FOR REPOSITORY
1368 #==============================================================================
1384 #==============================================================================
1369 class RepoPage(Page):
1385 class RepoPage(Page):
1370
1386
1371 def __init__(self, collection, page=1, items_per_page=20,
1387 def __init__(self, collection, page=1, items_per_page=20,
1372 item_count=None, url=None, **kwargs):
1388 item_count=None, url=None, **kwargs):
1373
1389
1374 """Create a "RepoPage" instance. special pager for paging
1390 """Create a "RepoPage" instance. special pager for paging
1375 repository
1391 repository
1376 """
1392 """
1377 self._url_generator = url
1393 self._url_generator = url
1378
1394
1379 # Safe the kwargs class-wide so they can be used in the pager() method
1395 # Safe the kwargs class-wide so they can be used in the pager() method
1380 self.kwargs = kwargs
1396 self.kwargs = kwargs
1381
1397
1382 # Save a reference to the collection
1398 # Save a reference to the collection
1383 self.original_collection = collection
1399 self.original_collection = collection
1384
1400
1385 self.collection = collection
1401 self.collection = collection
1386
1402
1387 # The self.page is the number of the current page.
1403 # The self.page is the number of the current page.
1388 # The first page has the number 1!
1404 # The first page has the number 1!
1389 try:
1405 try:
1390 self.page = int(page) # make it int() if we get it as a string
1406 self.page = int(page) # make it int() if we get it as a string
1391 except (ValueError, TypeError):
1407 except (ValueError, TypeError):
1392 self.page = 1
1408 self.page = 1
1393
1409
1394 self.items_per_page = items_per_page
1410 self.items_per_page = items_per_page
1395
1411
1396 # Unless the user tells us how many items the collections has
1412 # Unless the user tells us how many items the collections has
1397 # we calculate that ourselves.
1413 # we calculate that ourselves.
1398 if item_count is not None:
1414 if item_count is not None:
1399 self.item_count = item_count
1415 self.item_count = item_count
1400 else:
1416 else:
1401 self.item_count = len(self.collection)
1417 self.item_count = len(self.collection)
1402
1418
1403 # Compute the number of the first and last available page
1419 # Compute the number of the first and last available page
1404 if self.item_count > 0:
1420 if self.item_count > 0:
1405 self.first_page = 1
1421 self.first_page = 1
1406 self.page_count = int(math.ceil(float(self.item_count) /
1422 self.page_count = int(math.ceil(float(self.item_count) /
1407 self.items_per_page))
1423 self.items_per_page))
1408 self.last_page = self.first_page + self.page_count - 1
1424 self.last_page = self.first_page + self.page_count - 1
1409
1425
1410 # Make sure that the requested page number is the range of
1426 # Make sure that the requested page number is the range of
1411 # valid pages
1427 # valid pages
1412 if self.page > self.last_page:
1428 if self.page > self.last_page:
1413 self.page = self.last_page
1429 self.page = self.last_page
1414 elif self.page < self.first_page:
1430 elif self.page < self.first_page:
1415 self.page = self.first_page
1431 self.page = self.first_page
1416
1432
1417 # Note: the number of items on this page can be less than
1433 # Note: the number of items on this page can be less than
1418 # items_per_page if the last page is not full
1434 # items_per_page if the last page is not full
1419 self.first_item = max(0, (self.item_count) - (self.page *
1435 self.first_item = max(0, (self.item_count) - (self.page *
1420 items_per_page))
1436 items_per_page))
1421 self.last_item = ((self.item_count - 1) - items_per_page *
1437 self.last_item = ((self.item_count - 1) - items_per_page *
1422 (self.page - 1))
1438 (self.page - 1))
1423
1439
1424 self.items = list(self.collection[self.first_item:self.last_item + 1])
1440 self.items = list(self.collection[self.first_item:self.last_item + 1])
1425
1441
1426 # Links to previous and next page
1442 # Links to previous and next page
1427 if self.page > self.first_page:
1443 if self.page > self.first_page:
1428 self.previous_page = self.page - 1
1444 self.previous_page = self.page - 1
1429 else:
1445 else:
1430 self.previous_page = None
1446 self.previous_page = None
1431
1447
1432 if self.page < self.last_page:
1448 if self.page < self.last_page:
1433 self.next_page = self.page + 1
1449 self.next_page = self.page + 1
1434 else:
1450 else:
1435 self.next_page = None
1451 self.next_page = None
1436
1452
1437 # No items available
1453 # No items available
1438 else:
1454 else:
1439 self.first_page = None
1455 self.first_page = None
1440 self.page_count = 0
1456 self.page_count = 0
1441 self.last_page = None
1457 self.last_page = None
1442 self.first_item = None
1458 self.first_item = None
1443 self.last_item = None
1459 self.last_item = None
1444 self.previous_page = None
1460 self.previous_page = None
1445 self.next_page = None
1461 self.next_page = None
1446 self.items = []
1462 self.items = []
1447
1463
1448 # This is a subclass of the 'list' type. Initialise the list now.
1464 # This is a subclass of the 'list' type. Initialise the list now.
1449 list.__init__(self, reversed(self.items))
1465 list.__init__(self, reversed(self.items))
1450
1466
1451
1467
1452 def changed_tooltip(nodes):
1468 def changed_tooltip(nodes):
1453 """
1469 """
1454 Generates a html string for changed nodes in commit page.
1470 Generates a html string for changed nodes in commit page.
1455 It limits the output to 30 entries
1471 It limits the output to 30 entries
1456
1472
1457 :param nodes: LazyNodesGenerator
1473 :param nodes: LazyNodesGenerator
1458 """
1474 """
1459 if nodes:
1475 if nodes:
1460 pref = ': <br/> '
1476 pref = ': <br/> '
1461 suf = ''
1477 suf = ''
1462 if len(nodes) > 30:
1478 if len(nodes) > 30:
1463 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
1479 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
1464 return literal(pref + '<br/> '.join([safe_unicode(x.path)
1480 return literal(pref + '<br/> '.join([safe_unicode(x.path)
1465 for x in nodes[:30]]) + suf)
1481 for x in nodes[:30]]) + suf)
1466 else:
1482 else:
1467 return ': ' + _('No Files')
1483 return ': ' + _('No Files')
1468
1484
1469
1485
1470 def breadcrumb_repo_link(repo):
1486 def breadcrumb_repo_link(repo):
1471 """
1487 """
1472 Makes a breadcrumbs path link to repo
1488 Makes a breadcrumbs path link to repo
1473
1489
1474 ex::
1490 ex::
1475 group >> subgroup >> repo
1491 group >> subgroup >> repo
1476
1492
1477 :param repo: a Repository instance
1493 :param repo: a Repository instance
1478 """
1494 """
1479
1495
1480 path = [
1496 path = [
1481 link_to(group.name, url('repo_group_home', group_name=group.group_name))
1497 link_to(group.name, url('repo_group_home', group_name=group.group_name))
1482 for group in repo.groups_with_parents
1498 for group in repo.groups_with_parents
1483 ] + [
1499 ] + [
1484 link_to(repo.just_name, url('summary_home', repo_name=repo.repo_name))
1500 link_to(repo.just_name, url('summary_home', repo_name=repo.repo_name))
1485 ]
1501 ]
1486
1502
1487 return literal(' &raquo; '.join(path))
1503 return literal(' &raquo; '.join(path))
1488
1504
1489
1505
1490 def format_byte_size_binary(file_size):
1506 def format_byte_size_binary(file_size):
1491 """
1507 """
1492 Formats file/folder sizes to standard.
1508 Formats file/folder sizes to standard.
1493 """
1509 """
1494 formatted_size = format_byte_size(file_size, binary=True)
1510 formatted_size = format_byte_size(file_size, binary=True)
1495 return formatted_size
1511 return formatted_size
1496
1512
1497
1513
1498 def fancy_file_stats(stats):
1514 def fancy_file_stats(stats):
1499 """
1515 """
1500 Displays a fancy two colored bar for number of added/deleted
1516 Displays a fancy two colored bar for number of added/deleted
1501 lines of code on file
1517 lines of code on file
1502
1518
1503 :param stats: two element list of added/deleted lines of code
1519 :param stats: two element list of added/deleted lines of code
1504 """
1520 """
1505 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
1521 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
1506 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
1522 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
1507
1523
1508 def cgen(l_type, a_v, d_v):
1524 def cgen(l_type, a_v, d_v):
1509 mapping = {'tr': 'top-right-rounded-corner-mid',
1525 mapping = {'tr': 'top-right-rounded-corner-mid',
1510 'tl': 'top-left-rounded-corner-mid',
1526 'tl': 'top-left-rounded-corner-mid',
1511 'br': 'bottom-right-rounded-corner-mid',
1527 'br': 'bottom-right-rounded-corner-mid',
1512 'bl': 'bottom-left-rounded-corner-mid'}
1528 'bl': 'bottom-left-rounded-corner-mid'}
1513 map_getter = lambda x: mapping[x]
1529 map_getter = lambda x: mapping[x]
1514
1530
1515 if l_type == 'a' and d_v:
1531 if l_type == 'a' and d_v:
1516 #case when added and deleted are present
1532 #case when added and deleted are present
1517 return ' '.join(map(map_getter, ['tl', 'bl']))
1533 return ' '.join(map(map_getter, ['tl', 'bl']))
1518
1534
1519 if l_type == 'a' and not d_v:
1535 if l_type == 'a' and not d_v:
1520 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1536 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1521
1537
1522 if l_type == 'd' and a_v:
1538 if l_type == 'd' and a_v:
1523 return ' '.join(map(map_getter, ['tr', 'br']))
1539 return ' '.join(map(map_getter, ['tr', 'br']))
1524
1540
1525 if l_type == 'd' and not a_v:
1541 if l_type == 'd' and not a_v:
1526 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1542 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1527
1543
1528 a, d = stats['added'], stats['deleted']
1544 a, d = stats['added'], stats['deleted']
1529 width = 100
1545 width = 100
1530
1546
1531 if stats['binary']: # binary operations like chmod/rename etc
1547 if stats['binary']: # binary operations like chmod/rename etc
1532 lbl = []
1548 lbl = []
1533 bin_op = 0 # undefined
1549 bin_op = 0 # undefined
1534
1550
1535 # prefix with bin for binary files
1551 # prefix with bin for binary files
1536 if BIN_FILENODE in stats['ops']:
1552 if BIN_FILENODE in stats['ops']:
1537 lbl += ['bin']
1553 lbl += ['bin']
1538
1554
1539 if NEW_FILENODE in stats['ops']:
1555 if NEW_FILENODE in stats['ops']:
1540 lbl += [_('new file')]
1556 lbl += [_('new file')]
1541 bin_op = NEW_FILENODE
1557 bin_op = NEW_FILENODE
1542 elif MOD_FILENODE in stats['ops']:
1558 elif MOD_FILENODE in stats['ops']:
1543 lbl += [_('mod')]
1559 lbl += [_('mod')]
1544 bin_op = MOD_FILENODE
1560 bin_op = MOD_FILENODE
1545 elif DEL_FILENODE in stats['ops']:
1561 elif DEL_FILENODE in stats['ops']:
1546 lbl += [_('del')]
1562 lbl += [_('del')]
1547 bin_op = DEL_FILENODE
1563 bin_op = DEL_FILENODE
1548 elif RENAMED_FILENODE in stats['ops']:
1564 elif RENAMED_FILENODE in stats['ops']:
1549 lbl += [_('rename')]
1565 lbl += [_('rename')]
1550 bin_op = RENAMED_FILENODE
1566 bin_op = RENAMED_FILENODE
1551
1567
1552 # chmod can go with other operations, so we add a + to lbl if needed
1568 # chmod can go with other operations, so we add a + to lbl if needed
1553 if CHMOD_FILENODE in stats['ops']:
1569 if CHMOD_FILENODE in stats['ops']:
1554 lbl += [_('chmod')]
1570 lbl += [_('chmod')]
1555 if bin_op == 0:
1571 if bin_op == 0:
1556 bin_op = CHMOD_FILENODE
1572 bin_op = CHMOD_FILENODE
1557
1573
1558 lbl = '+'.join(lbl)
1574 lbl = '+'.join(lbl)
1559 b_a = '<div class="bin bin%s %s" style="width:100%%">%s</div>' \
1575 b_a = '<div class="bin bin%s %s" style="width:100%%">%s</div>' \
1560 % (bin_op, cgen('a', a_v='', d_v=0), lbl)
1576 % (bin_op, cgen('a', a_v='', d_v=0), lbl)
1561 b_d = '<div class="bin bin1" style="width:0%%"></div>'
1577 b_d = '<div class="bin bin1" style="width:0%%"></div>'
1562 return literal('<div style="width:%spx">%s%s</div>' % (width, b_a, b_d))
1578 return literal('<div style="width:%spx">%s%s</div>' % (width, b_a, b_d))
1563
1579
1564 t = stats['added'] + stats['deleted']
1580 t = stats['added'] + stats['deleted']
1565 unit = float(width) / (t or 1)
1581 unit = float(width) / (t or 1)
1566
1582
1567 # needs > 9% of width to be visible or 0 to be hidden
1583 # needs > 9% of width to be visible or 0 to be hidden
1568 a_p = max(9, unit * a) if a > 0 else 0
1584 a_p = max(9, unit * a) if a > 0 else 0
1569 d_p = max(9, unit * d) if d > 0 else 0
1585 d_p = max(9, unit * d) if d > 0 else 0
1570 p_sum = a_p + d_p
1586 p_sum = a_p + d_p
1571
1587
1572 if p_sum > width:
1588 if p_sum > width:
1573 #adjust the percentage to be == 100% since we adjusted to 9
1589 #adjust the percentage to be == 100% since we adjusted to 9
1574 if a_p > d_p:
1590 if a_p > d_p:
1575 a_p = a_p - (p_sum - width)
1591 a_p = a_p - (p_sum - width)
1576 else:
1592 else:
1577 d_p = d_p - (p_sum - width)
1593 d_p = d_p - (p_sum - width)
1578
1594
1579 a_v = a if a > 0 else ''
1595 a_v = a if a > 0 else ''
1580 d_v = d if d > 0 else ''
1596 d_v = d if d > 0 else ''
1581
1597
1582 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
1598 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
1583 cgen('a', a_v, d_v), a_p, a_v
1599 cgen('a', a_v, d_v), a_p, a_v
1584 )
1600 )
1585 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
1601 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
1586 cgen('d', a_v, d_v), d_p, d_v
1602 cgen('d', a_v, d_v), d_p, d_v
1587 )
1603 )
1588 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
1604 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
1589
1605
1590
1606
1591 def urlify_text(text_, safe=True):
1607 def urlify_text(text_, safe=True):
1592 """
1608 """
1593 Extrac urls from text and make html links out of them
1609 Extrac urls from text and make html links out of them
1594
1610
1595 :param text_:
1611 :param text_:
1596 """
1612 """
1597
1613
1598 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1614 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1599 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1615 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1600
1616
1601 def url_func(match_obj):
1617 def url_func(match_obj):
1602 url_full = match_obj.groups()[0]
1618 url_full = match_obj.groups()[0]
1603 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1619 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1604 _newtext = url_pat.sub(url_func, text_)
1620 _newtext = url_pat.sub(url_func, text_)
1605 if safe:
1621 if safe:
1606 return literal(_newtext)
1622 return literal(_newtext)
1607 return _newtext
1623 return _newtext
1608
1624
1609
1625
1610 def urlify_commits(text_, repository):
1626 def urlify_commits(text_, repository):
1611 """
1627 """
1612 Extract commit ids from text and make link from them
1628 Extract commit ids from text and make link from them
1613
1629
1614 :param text_:
1630 :param text_:
1615 :param repository: repo name to build the URL with
1631 :param repository: repo name to build the URL with
1616 """
1632 """
1617 from pylons import url # doh, we need to re-import url to mock it later
1633 from pylons import url # doh, we need to re-import url to mock it later
1618 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1634 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1619
1635
1620 def url_func(match_obj):
1636 def url_func(match_obj):
1621 commit_id = match_obj.groups()[1]
1637 commit_id = match_obj.groups()[1]
1622 pref = match_obj.groups()[0]
1638 pref = match_obj.groups()[0]
1623 suf = match_obj.groups()[2]
1639 suf = match_obj.groups()[2]
1624
1640
1625 tmpl = (
1641 tmpl = (
1626 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1642 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1627 '%(commit_id)s</a>%(suf)s'
1643 '%(commit_id)s</a>%(suf)s'
1628 )
1644 )
1629 return tmpl % {
1645 return tmpl % {
1630 'pref': pref,
1646 'pref': pref,
1631 'cls': 'revision-link',
1647 'cls': 'revision-link',
1632 'url': url('changeset_home', repo_name=repository,
1648 'url': url('changeset_home', repo_name=repository,
1633 revision=commit_id, qualified=True),
1649 revision=commit_id, qualified=True),
1634 'commit_id': commit_id,
1650 'commit_id': commit_id,
1635 'suf': suf
1651 'suf': suf
1636 }
1652 }
1637
1653
1638 newtext = URL_PAT.sub(url_func, text_)
1654 newtext = URL_PAT.sub(url_func, text_)
1639
1655
1640 return newtext
1656 return newtext
1641
1657
1642
1658
1643 def _process_url_func(match_obj, repo_name, uid, entry,
1659 def _process_url_func(match_obj, repo_name, uid, entry,
1644 return_raw_data=False):
1660 return_raw_data=False):
1645 pref = ''
1661 pref = ''
1646 if match_obj.group().startswith(' '):
1662 if match_obj.group().startswith(' '):
1647 pref = ' '
1663 pref = ' '
1648
1664
1649 issue_id = ''.join(match_obj.groups())
1665 issue_id = ''.join(match_obj.groups())
1650 tmpl = (
1666 tmpl = (
1651 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1667 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1652 '%(issue-prefix)s%(id-repr)s'
1668 '%(issue-prefix)s%(id-repr)s'
1653 '</a>')
1669 '</a>')
1654
1670
1655 (repo_name_cleaned,
1671 (repo_name_cleaned,
1656 parent_group_name) = RepoGroupModel().\
1672 parent_group_name) = RepoGroupModel().\
1657 _get_group_name_and_parent(repo_name)
1673 _get_group_name_and_parent(repo_name)
1658
1674
1659 # variables replacement
1675 # variables replacement
1660 named_vars = {
1676 named_vars = {
1661 'id': issue_id,
1677 'id': issue_id,
1662 'repo': repo_name,
1678 'repo': repo_name,
1663 'repo_name': repo_name_cleaned,
1679 'repo_name': repo_name_cleaned,
1664 'group_name': parent_group_name
1680 'group_name': parent_group_name
1665 }
1681 }
1666 # named regex variables
1682 # named regex variables
1667 named_vars.update(match_obj.groupdict())
1683 named_vars.update(match_obj.groupdict())
1668 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1684 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1669
1685
1670 data = {
1686 data = {
1671 'pref': pref,
1687 'pref': pref,
1672 'cls': 'issue-tracker-link',
1688 'cls': 'issue-tracker-link',
1673 'url': _url,
1689 'url': _url,
1674 'id-repr': issue_id,
1690 'id-repr': issue_id,
1675 'issue-prefix': entry['pref'],
1691 'issue-prefix': entry['pref'],
1676 'serv': entry['url'],
1692 'serv': entry['url'],
1677 }
1693 }
1678 if return_raw_data:
1694 if return_raw_data:
1679 return {
1695 return {
1680 'id': issue_id,
1696 'id': issue_id,
1681 'url': _url
1697 'url': _url
1682 }
1698 }
1683 return tmpl % data
1699 return tmpl % data
1684
1700
1685
1701
1686 def process_patterns(text_string, repo_name, config=None):
1702 def process_patterns(text_string, repo_name, config=None):
1687 repo = None
1703 repo = None
1688 if repo_name:
1704 if repo_name:
1689 # Retrieving repo_name to avoid invalid repo_name to explode on
1705 # Retrieving repo_name to avoid invalid repo_name to explode on
1690 # IssueTrackerSettingsModel but still passing invalid name further down
1706 # IssueTrackerSettingsModel but still passing invalid name further down
1691 repo = Repository.get_by_repo_name(repo_name, cache=True)
1707 repo = Repository.get_by_repo_name(repo_name, cache=True)
1692
1708
1693 settings_model = IssueTrackerSettingsModel(repo=repo)
1709 settings_model = IssueTrackerSettingsModel(repo=repo)
1694 active_entries = settings_model.get_settings(cache=True)
1710 active_entries = settings_model.get_settings(cache=True)
1695
1711
1696 issues_data = []
1712 issues_data = []
1697 newtext = text_string
1713 newtext = text_string
1698 for uid, entry in active_entries.items():
1714 for uid, entry in active_entries.items():
1699 log.debug('found issue tracker entry with uid %s' % (uid,))
1715 log.debug('found issue tracker entry with uid %s' % (uid,))
1700
1716
1701 if not (entry['pat'] and entry['url']):
1717 if not (entry['pat'] and entry['url']):
1702 log.debug('skipping due to missing data')
1718 log.debug('skipping due to missing data')
1703 continue
1719 continue
1704
1720
1705 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s'
1721 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s'
1706 % (uid, entry['pat'], entry['url'], entry['pref']))
1722 % (uid, entry['pat'], entry['url'], entry['pref']))
1707
1723
1708 try:
1724 try:
1709 pattern = re.compile(r'%s' % entry['pat'])
1725 pattern = re.compile(r'%s' % entry['pat'])
1710 except re.error:
1726 except re.error:
1711 log.exception(
1727 log.exception(
1712 'issue tracker pattern: `%s` failed to compile',
1728 'issue tracker pattern: `%s` failed to compile',
1713 entry['pat'])
1729 entry['pat'])
1714 continue
1730 continue
1715
1731
1716 data_func = partial(
1732 data_func = partial(
1717 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1733 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1718 return_raw_data=True)
1734 return_raw_data=True)
1719
1735
1720 for match_obj in pattern.finditer(text_string):
1736 for match_obj in pattern.finditer(text_string):
1721 issues_data.append(data_func(match_obj))
1737 issues_data.append(data_func(match_obj))
1722
1738
1723 url_func = partial(
1739 url_func = partial(
1724 _process_url_func, repo_name=repo_name, entry=entry, uid=uid)
1740 _process_url_func, repo_name=repo_name, entry=entry, uid=uid)
1725
1741
1726 newtext = pattern.sub(url_func, newtext)
1742 newtext = pattern.sub(url_func, newtext)
1727 log.debug('processed prefix:uid `%s`' % (uid,))
1743 log.debug('processed prefix:uid `%s`' % (uid,))
1728
1744
1729 return newtext, issues_data
1745 return newtext, issues_data
1730
1746
1731
1747
1732 def urlify_commit_message(commit_text, repository=None):
1748 def urlify_commit_message(commit_text, repository=None):
1733 """
1749 """
1734 Parses given text message and makes proper links.
1750 Parses given text message and makes proper links.
1735 issues are linked to given issue-server, and rest is a commit link
1751 issues are linked to given issue-server, and rest is a commit link
1736
1752
1737 :param commit_text:
1753 :param commit_text:
1738 :param repository:
1754 :param repository:
1739 """
1755 """
1740 from pylons import url # doh, we need to re-import url to mock it later
1756 from pylons import url # doh, we need to re-import url to mock it later
1741
1757
1742 def escaper(string):
1758 def escaper(string):
1743 return string.replace('<', '&lt;').replace('>', '&gt;')
1759 return string.replace('<', '&lt;').replace('>', '&gt;')
1744
1760
1745 newtext = escaper(commit_text)
1761 newtext = escaper(commit_text)
1746
1762
1747 # extract http/https links and make them real urls
1763 # extract http/https links and make them real urls
1748 newtext = urlify_text(newtext, safe=False)
1764 newtext = urlify_text(newtext, safe=False)
1749
1765
1750 # urlify commits - extract commit ids and make link out of them, if we have
1766 # urlify commits - extract commit ids and make link out of them, if we have
1751 # the scope of repository present.
1767 # the scope of repository present.
1752 if repository:
1768 if repository:
1753 newtext = urlify_commits(newtext, repository)
1769 newtext = urlify_commits(newtext, repository)
1754
1770
1755 # process issue tracker patterns
1771 # process issue tracker patterns
1756 newtext, issues = process_patterns(newtext, repository or '')
1772 newtext, issues = process_patterns(newtext, repository or '')
1757
1773
1758 return literal(newtext)
1774 return literal(newtext)
1759
1775
1760
1776
1761 def rst(source, mentions=False):
1777 def rst(source, mentions=False):
1762 return literal('<div class="rst-block">%s</div>' %
1778 return literal('<div class="rst-block">%s</div>' %
1763 MarkupRenderer.rst(source, mentions=mentions))
1779 MarkupRenderer.rst(source, mentions=mentions))
1764
1780
1765
1781
1766 def markdown(source, mentions=False):
1782 def markdown(source, mentions=False):
1767 return literal('<div class="markdown-block">%s</div>' %
1783 return literal('<div class="markdown-block">%s</div>' %
1768 MarkupRenderer.markdown(source, flavored=True,
1784 MarkupRenderer.markdown(source, flavored=True,
1769 mentions=mentions))
1785 mentions=mentions))
1770
1786
1771 def renderer_from_filename(filename, exclude=None):
1787 def renderer_from_filename(filename, exclude=None):
1772 return MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1788 return MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1773
1789
1774
1790
1775 def render(source, renderer='rst', mentions=False):
1791 def render(source, renderer='rst', mentions=False):
1776 if renderer == 'rst':
1792 if renderer == 'rst':
1777 return rst(source, mentions=mentions)
1793 return rst(source, mentions=mentions)
1778 if renderer == 'markdown':
1794 if renderer == 'markdown':
1779 return markdown(source, mentions=mentions)
1795 return markdown(source, mentions=mentions)
1780
1796
1781
1797
1782 def commit_status(repo, commit_id):
1798 def commit_status(repo, commit_id):
1783 return ChangesetStatusModel().get_status(repo, commit_id)
1799 return ChangesetStatusModel().get_status(repo, commit_id)
1784
1800
1785
1801
1786 def commit_status_lbl(commit_status):
1802 def commit_status_lbl(commit_status):
1787 return dict(ChangesetStatus.STATUSES).get(commit_status)
1803 return dict(ChangesetStatus.STATUSES).get(commit_status)
1788
1804
1789
1805
1790 def commit_time(repo_name, commit_id):
1806 def commit_time(repo_name, commit_id):
1791 repo = Repository.get_by_repo_name(repo_name)
1807 repo = Repository.get_by_repo_name(repo_name)
1792 commit = repo.get_commit(commit_id=commit_id)
1808 commit = repo.get_commit(commit_id=commit_id)
1793 return commit.date
1809 return commit.date
1794
1810
1795
1811
1796 def get_permission_name(key):
1812 def get_permission_name(key):
1797 return dict(Permission.PERMS).get(key)
1813 return dict(Permission.PERMS).get(key)
1798
1814
1799
1815
1800 def journal_filter_help():
1816 def journal_filter_help():
1801 return _(
1817 return _(
1802 'Example filter terms:\n' +
1818 'Example filter terms:\n' +
1803 ' repository:vcs\n' +
1819 ' repository:vcs\n' +
1804 ' username:marcin\n' +
1820 ' username:marcin\n' +
1805 ' action:*push*\n' +
1821 ' action:*push*\n' +
1806 ' ip:127.0.0.1\n' +
1822 ' ip:127.0.0.1\n' +
1807 ' date:20120101\n' +
1823 ' date:20120101\n' +
1808 ' date:[20120101100000 TO 20120102]\n' +
1824 ' date:[20120101100000 TO 20120102]\n' +
1809 '\n' +
1825 '\n' +
1810 'Generate wildcards using \'*\' character:\n' +
1826 'Generate wildcards using \'*\' character:\n' +
1811 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1827 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1812 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1828 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1813 '\n' +
1829 '\n' +
1814 'Optional AND / OR operators in queries\n' +
1830 'Optional AND / OR operators in queries\n' +
1815 ' "repository:vcs OR repository:test"\n' +
1831 ' "repository:vcs OR repository:test"\n' +
1816 ' "username:test AND repository:test*"\n'
1832 ' "username:test AND repository:test*"\n'
1817 )
1833 )
1818
1834
1819
1835
1820 def not_mapped_error(repo_name):
1836 def not_mapped_error(repo_name):
1821 flash(_('%s repository is not mapped to db perhaps'
1837 flash(_('%s repository is not mapped to db perhaps'
1822 ' it was created or renamed from the filesystem'
1838 ' it was created or renamed from the filesystem'
1823 ' please run the application again'
1839 ' please run the application again'
1824 ' in order to rescan repositories') % repo_name, category='error')
1840 ' in order to rescan repositories') % repo_name, category='error')
1825
1841
1826
1842
1827 def ip_range(ip_addr):
1843 def ip_range(ip_addr):
1828 from rhodecode.model.db import UserIpMap
1844 from rhodecode.model.db import UserIpMap
1829 s, e = UserIpMap._get_ip_range(ip_addr)
1845 s, e = UserIpMap._get_ip_range(ip_addr)
1830 return '%s - %s' % (s, e)
1846 return '%s - %s' % (s, e)
1831
1847
1832
1848
1833 def form(url, method='post', needs_csrf_token=True, **attrs):
1849 def form(url, method='post', needs_csrf_token=True, **attrs):
1834 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1850 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1835 if method.lower() != 'get' and needs_csrf_token:
1851 if method.lower() != 'get' and needs_csrf_token:
1836 raise Exception(
1852 raise Exception(
1837 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1853 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1838 'CSRF token. If the endpoint does not require such token you can ' +
1854 'CSRF token. If the endpoint does not require such token you can ' +
1839 'explicitly set the parameter needs_csrf_token to false.')
1855 'explicitly set the parameter needs_csrf_token to false.')
1840
1856
1841 return wh_form(url, method=method, **attrs)
1857 return wh_form(url, method=method, **attrs)
1842
1858
1843
1859
1844 def secure_form(url, method="POST", multipart=False, **attrs):
1860 def secure_form(url, method="POST", multipart=False, **attrs):
1845 """Start a form tag that points the action to an url. This
1861 """Start a form tag that points the action to an url. This
1846 form tag will also include the hidden field containing
1862 form tag will also include the hidden field containing
1847 the auth token.
1863 the auth token.
1848
1864
1849 The url options should be given either as a string, or as a
1865 The url options should be given either as a string, or as a
1850 ``url()`` function. The method for the form defaults to POST.
1866 ``url()`` function. The method for the form defaults to POST.
1851
1867
1852 Options:
1868 Options:
1853
1869
1854 ``multipart``
1870 ``multipart``
1855 If set to True, the enctype is set to "multipart/form-data".
1871 If set to True, the enctype is set to "multipart/form-data".
1856 ``method``
1872 ``method``
1857 The method to use when submitting the form, usually either
1873 The method to use when submitting the form, usually either
1858 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1874 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1859 hidden input with name _method is added to simulate the verb
1875 hidden input with name _method is added to simulate the verb
1860 over POST.
1876 over POST.
1861
1877
1862 """
1878 """
1863 from webhelpers.pylonslib.secure_form import insecure_form
1879 from webhelpers.pylonslib.secure_form import insecure_form
1864 from rhodecode.lib.auth import get_csrf_token, csrf_token_key
1880 from rhodecode.lib.auth import get_csrf_token, csrf_token_key
1865 form = insecure_form(url, method, multipart, **attrs)
1881 form = insecure_form(url, method, multipart, **attrs)
1866 token = HTML.div(hidden(csrf_token_key, get_csrf_token()), style="display: none;")
1882 token = HTML.div(hidden(csrf_token_key, get_csrf_token()), style="display: none;")
1867 return literal("%s\n%s" % (form, token))
1883 return literal("%s\n%s" % (form, token))
1868
1884
1869 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1885 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1870 select_html = select(name, selected, options, **attrs)
1886 select_html = select(name, selected, options, **attrs)
1871 select2 = """
1887 select2 = """
1872 <script>
1888 <script>
1873 $(document).ready(function() {
1889 $(document).ready(function() {
1874 $('#%s').select2({
1890 $('#%s').select2({
1875 containerCssClass: 'drop-menu',
1891 containerCssClass: 'drop-menu',
1876 dropdownCssClass: 'drop-menu-dropdown',
1892 dropdownCssClass: 'drop-menu-dropdown',
1877 dropdownAutoWidth: true%s
1893 dropdownAutoWidth: true%s
1878 });
1894 });
1879 });
1895 });
1880 </script>
1896 </script>
1881 """
1897 """
1882 filter_option = """,
1898 filter_option = """,
1883 minimumResultsForSearch: -1
1899 minimumResultsForSearch: -1
1884 """
1900 """
1885 input_id = attrs.get('id') or name
1901 input_id = attrs.get('id') or name
1886 filter_enabled = "" if enable_filter else filter_option
1902 filter_enabled = "" if enable_filter else filter_option
1887 select_script = literal(select2 % (input_id, filter_enabled))
1903 select_script = literal(select2 % (input_id, filter_enabled))
1888
1904
1889 return literal(select_html+select_script)
1905 return literal(select_html+select_script)
1890
1906
1891
1907
1892 def get_visual_attr(tmpl_context_var, attr_name):
1908 def get_visual_attr(tmpl_context_var, attr_name):
1893 """
1909 """
1894 A safe way to get a variable from visual variable of template context
1910 A safe way to get a variable from visual variable of template context
1895
1911
1896 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1912 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1897 :param attr_name: name of the attribute we fetch from the c.visual
1913 :param attr_name: name of the attribute we fetch from the c.visual
1898 """
1914 """
1899 visual = getattr(tmpl_context_var, 'visual', None)
1915 visual = getattr(tmpl_context_var, 'visual', None)
1900 if not visual:
1916 if not visual:
1901 return
1917 return
1902 else:
1918 else:
1903 return getattr(visual, attr_name, None)
1919 return getattr(visual, attr_name, None)
1904
1920
1905
1921
1906 def get_last_path_part(file_node):
1922 def get_last_path_part(file_node):
1907 if not file_node.path:
1923 if not file_node.path:
1908 return u''
1924 return u''
1909
1925
1910 path = safe_unicode(file_node.path.split('/')[-1])
1926 path = safe_unicode(file_node.path.split('/')[-1])
1911 return u'../' + path
1927 return u'../' + path
1912
1928
1913
1929
1914 def route_path(*args, **kwds):
1930 def route_path(*args, **kwds):
1915 """
1931 """
1916 Wrapper around pyramids `route_path` function. It is used to generate
1932 Wrapper around pyramids `route_path` function. It is used to generate
1917 URLs from within pylons views or templates. This will be removed when
1933 URLs from within pylons views or templates. This will be removed when
1918 pyramid migration if finished.
1934 pyramid migration if finished.
1919 """
1935 """
1920 req = get_current_request()
1936 req = get_current_request()
1921 return req.route_path(*args, **kwds)
1937 return req.route_path(*args, **kwds)
1922
1938
1923
1939
1924 def resource_path(*args, **kwds):
1940 def resource_path(*args, **kwds):
1925 """
1941 """
1926 Wrapper around pyramids `route_path` function. It is used to generate
1942 Wrapper around pyramids `route_path` function. It is used to generate
1927 URLs from within pylons views or templates. This will be removed when
1943 URLs from within pylons views or templates. This will be removed when
1928 pyramid migration if finished.
1944 pyramid migration if finished.
1929 """
1945 """
1930 req = get_current_request()
1946 req = get_current_request()
1931 return req.resource_path(*args, **kwds)
1947 return req.resource_path(*args, **kwds)
@@ -1,656 +1,656 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <div class="outerwrapper">
4 <div class="outerwrapper">
5 <!-- HEADER -->
5 <!-- HEADER -->
6 <div class="header">
6 <div class="header">
7 <div id="header-inner" class="wrapper">
7 <div id="header-inner" class="wrapper">
8 <div id="logo">
8 <div id="logo">
9 <div class="logo-wrapper">
9 <div class="logo-wrapper">
10 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
10 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
11 </div>
11 </div>
12 %if c.rhodecode_name:
12 %if c.rhodecode_name:
13 <div class="branding">- ${h.branding(c.rhodecode_name)}</div>
13 <div class="branding">- ${h.branding(c.rhodecode_name)}</div>
14 %endif
14 %endif
15 </div>
15 </div>
16 <!-- MENU BAR NAV -->
16 <!-- MENU BAR NAV -->
17 ${self.menu_bar_nav()}
17 ${self.menu_bar_nav()}
18 <!-- END MENU BAR NAV -->
18 <!-- END MENU BAR NAV -->
19 </div>
19 </div>
20 </div>
20 </div>
21 ${self.menu_bar_subnav()}
21 ${self.menu_bar_subnav()}
22 <!-- END HEADER -->
22 <!-- END HEADER -->
23
23
24 <!-- CONTENT -->
24 <!-- CONTENT -->
25 <div id="content" class="wrapper">
25 <div id="content" class="wrapper">
26 ${self.flash_msg()}
26 ${self.flash_msg()}
27 <div class="main">
27 <div class="main">
28 ${next.main()}
28 ${next.main()}
29 </div>
29 </div>
30 </div>
30 </div>
31 <!-- END CONTENT -->
31 <!-- END CONTENT -->
32
32
33 </div>
33 </div>
34 <!-- FOOTER -->
34 <!-- FOOTER -->
35 <div id="footer">
35 <div id="footer">
36 <div id="footer-inner" class="title wrapper">
36 <div id="footer-inner" class="title wrapper">
37 <div>
37 <div>
38 <p class="footer-link-right">
38 <p class="footer-link-right">
39 % if c.visual.show_version:
39 % if c.visual.show_version:
40 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
40 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
41 % endif
41 % endif
42 &copy; 2010-${h.datetime.today().year}, <a href="${h.url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
42 &copy; 2010-${h.datetime.today().year}, <a href="${h.url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
43 % if c.visual.rhodecode_support_url:
43 % if c.visual.rhodecode_support_url:
44 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
44 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
45 % endif
45 % endif
46 </p>
46 </p>
47 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
47 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
48 <p class="server-instance" style="display:${sid}">
48 <p class="server-instance" style="display:${sid}">
49 ## display hidden instance ID if specially defined
49 ## display hidden instance ID if specially defined
50 % if c.rhodecode_instanceid:
50 % if c.rhodecode_instanceid:
51 ${_('RhodeCode instance id: %s') % c.rhodecode_instanceid}
51 ${_('RhodeCode instance id: %s') % c.rhodecode_instanceid}
52 % endif
52 % endif
53 </p>
53 </p>
54 </div>
54 </div>
55 </div>
55 </div>
56 </div>
56 </div>
57
57
58 <!-- END FOOTER -->
58 <!-- END FOOTER -->
59
59
60 ### MAKO DEFS ###
60 ### MAKO DEFS ###
61
61
62 <%def name="menu_bar_subnav()">
62 <%def name="menu_bar_subnav()">
63 </%def>
63 </%def>
64
64
65 <%def name="flash_msg()">
65 <%def name="flash_msg()">
66 <%include file="/base/flash_msg.html"/>
66 <%include file="/base/flash_msg.html"/>
67 </%def>
67 </%def>
68
68
69 <%def name="breadcrumbs(class_='breadcrumbs')">
69 <%def name="breadcrumbs(class_='breadcrumbs')">
70 <div class="${class_}">
70 <div class="${class_}">
71 ${self.breadcrumbs_links()}
71 ${self.breadcrumbs_links()}
72 </div>
72 </div>
73 </%def>
73 </%def>
74
74
75 <%def name="admin_menu()">
75 <%def name="admin_menu()">
76 <ul class="admin_menu submenu">
76 <ul class="admin_menu submenu">
77 <li><a href="${h.url('admin_home')}">${_('Admin journal')}</a></li>
77 <li><a href="${h.url('admin_home')}">${_('Admin journal')}</a></li>
78 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
78 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
79 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
79 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
80 <li><a href="${h.url('users')}">${_('Users')}</a></li>
80 <li><a href="${h.url('users')}">${_('Users')}</a></li>
81 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
81 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
82 <li><a href="${h.url('admin_permissions_application')}">${_('Permissions')}</a></li>
82 <li><a href="${h.url('admin_permissions_application')}">${_('Permissions')}</a></li>
83 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
83 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
84 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
84 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
85 <li><a href="${h.url('admin_defaults_repositories')}">${_('Defaults')}</a></li>
85 <li><a href="${h.url('admin_defaults_repositories')}">${_('Defaults')}</a></li>
86 <li class="last"><a href="${h.url('admin_settings')}">${_('Settings')}</a></li>
86 <li class="last"><a href="${h.url('admin_settings')}">${_('Settings')}</a></li>
87 </ul>
87 </ul>
88 </%def>
88 </%def>
89
89
90
90
91 <%def name="dt_info_panel(elements)">
91 <%def name="dt_info_panel(elements)">
92 <dl class="dl-horizontal">
92 <dl class="dl-horizontal">
93 %for dt, dd, title, show_items in elements:
93 %for dt, dd, title, show_items in elements:
94 <dt>${dt}:</dt>
94 <dt>${dt}:</dt>
95 <dd title="${title}">
95 <dd title="${title}">
96 %if callable(dd):
96 %if callable(dd):
97 ## allow lazy evaluation of elements
97 ## allow lazy evaluation of elements
98 ${dd()}
98 ${dd()}
99 %else:
99 %else:
100 ${dd}
100 ${dd}
101 %endif
101 %endif
102 %if show_items:
102 %if show_items:
103 <span class="btn-collapse" data-toggle="item-${h.md5(dt)[:6]}-details">${_('Show More')} </span>
103 <span class="btn-collapse" data-toggle="item-${h.md5(dt)[:6]}-details">${_('Show More')} </span>
104 %endif
104 %endif
105 </dd>
105 </dd>
106
106
107 %if show_items:
107 %if show_items:
108 <div class="collapsable-content" data-toggle="item-${h.md5(dt)[:6]}-details" style="display: none">
108 <div class="collapsable-content" data-toggle="item-${h.md5(dt)[:6]}-details" style="display: none">
109 %for item in show_items:
109 %for item in show_items:
110 <dt></dt>
110 <dt></dt>
111 <dd>${item}</dd>
111 <dd>${item}</dd>
112 %endfor
112 %endfor
113 </div>
113 </div>
114 %endif
114 %endif
115
115
116 %endfor
116 %endfor
117 </dl>
117 </dl>
118 </%def>
118 </%def>
119
119
120
120
121 <%def name="gravatar(email, size=16)">
121 <%def name="gravatar(email, size=16)">
122 <%
122 <%
123 if (size > 16):
123 if (size > 16):
124 gravatar_class = 'gravatar gravatar-large'
124 gravatar_class = 'gravatar gravatar-large'
125 else:
125 else:
126 gravatar_class = 'gravatar'
126 gravatar_class = 'gravatar'
127 %>
127 %>
128 <%doc>
128 <%doc>
129 TODO: johbo: For now we serve double size images to make it smooth
129 TODO: johbo: For now we serve double size images to make it smooth
130 for retina. This is how it worked until now. Should be replaced
130 for retina. This is how it worked until now. Should be replaced
131 with a better solution at some point.
131 with a better solution at some point.
132 </%doc>
132 </%doc>
133 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
133 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
134 </%def>
134 </%def>
135
135
136
136
137 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
137 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
138 <% email = h.email_or_none(contact) %>
138 <% email = h.email_or_none(contact) %>
139 <div class="rc-user tooltip" title="${h.author_string(email)}">
139 <div class="rc-user tooltip" title="${h.author_string(email)}">
140 ${self.gravatar(email, size)}
140 ${self.gravatar(email, size)}
141 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
141 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
142 </div>
142 </div>
143 </%def>
143 </%def>
144
144
145
145
146 ## admin menu used for people that have some admin resources
146 ## admin menu used for people that have some admin resources
147 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
147 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
148 <ul class="submenu">
148 <ul class="submenu">
149 %if repositories:
149 %if repositories:
150 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
150 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
151 %endif
151 %endif
152 %if repository_groups:
152 %if repository_groups:
153 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
153 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
154 %endif
154 %endif
155 %if user_groups:
155 %if user_groups:
156 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
156 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
157 %endif
157 %endif
158 </ul>
158 </ul>
159 </%def>
159 </%def>
160
160
161 <%def name="repo_page_title(repo_instance)">
161 <%def name="repo_page_title(repo_instance)">
162 <div class="title-content">
162 <div class="title-content">
163 <div class="title-main">
163 <div class="title-main">
164 ## SVN/HG/GIT icons
164 ## SVN/HG/GIT icons
165 %if h.is_hg(repo_instance):
165 %if h.is_hg(repo_instance):
166 <i class="icon-hg"></i>
166 <i class="icon-hg"></i>
167 %endif
167 %endif
168 %if h.is_git(repo_instance):
168 %if h.is_git(repo_instance):
169 <i class="icon-git"></i>
169 <i class="icon-git"></i>
170 %endif
170 %endif
171 %if h.is_svn(repo_instance):
171 %if h.is_svn(repo_instance):
172 <i class="icon-svn"></i>
172 <i class="icon-svn"></i>
173 %endif
173 %endif
174
174
175 ## public/private
175 ## public/private
176 %if repo_instance.private:
176 %if repo_instance.private:
177 <i class="icon-repo-private"></i>
177 <i class="icon-repo-private"></i>
178 %else:
178 %else:
179 <i class="icon-repo-public"></i>
179 <i class="icon-repo-public"></i>
180 %endif
180 %endif
181
181
182 ## repo name with group name
182 ## repo name with group name
183 ${h.breadcrumb_repo_link(c.rhodecode_db_repo)}
183 ${h.breadcrumb_repo_link(c.rhodecode_db_repo)}
184
184
185 </div>
185 </div>
186
186
187 ## FORKED
187 ## FORKED
188 %if repo_instance.fork:
188 %if repo_instance.fork:
189 <p>
189 <p>
190 <i class="icon-code-fork"></i> ${_('Fork of')}
190 <i class="icon-code-fork"></i> ${_('Fork of')}
191 <a href="${h.url('summary_home',repo_name=repo_instance.fork.repo_name)}">${repo_instance.fork.repo_name}</a>
191 <a href="${h.url('summary_home',repo_name=repo_instance.fork.repo_name)}">${repo_instance.fork.repo_name}</a>
192 </p>
192 </p>
193 %endif
193 %endif
194
194
195 ## IMPORTED FROM REMOTE
195 ## IMPORTED FROM REMOTE
196 %if repo_instance.clone_uri:
196 %if repo_instance.clone_uri:
197 <p>
197 <p>
198 <i class="icon-code-fork"></i> ${_('Clone from')}
198 <i class="icon-code-fork"></i> ${_('Clone from')}
199 <a href="${h.url(h.safe_str(h.hide_credentials(repo_instance.clone_uri)))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
199 <a href="${h.url(h.safe_str(h.hide_credentials(repo_instance.clone_uri)))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
200 </p>
200 </p>
201 %endif
201 %endif
202
202
203 ## LOCKING STATUS
203 ## LOCKING STATUS
204 %if repo_instance.locked[0]:
204 %if repo_instance.locked[0]:
205 <p class="locking_locked">
205 <p class="locking_locked">
206 <i class="icon-repo-lock"></i>
206 <i class="icon-repo-lock"></i>
207 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
207 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
208 </p>
208 </p>
209 %elif repo_instance.enable_locking:
209 %elif repo_instance.enable_locking:
210 <p class="locking_unlocked">
210 <p class="locking_unlocked">
211 <i class="icon-repo-unlock"></i>
211 <i class="icon-repo-unlock"></i>
212 ${_('Repository not locked. Pull repository to lock it.')}
212 ${_('Repository not locked. Pull repository to lock it.')}
213 </p>
213 </p>
214 %endif
214 %endif
215
215
216 </div>
216 </div>
217 </%def>
217 </%def>
218
218
219 <%def name="repo_menu(active=None)">
219 <%def name="repo_menu(active=None)">
220 <%
220 <%
221 def is_active(selected):
221 def is_active(selected):
222 if selected == active:
222 if selected == active:
223 return "active"
223 return "active"
224 %>
224 %>
225
225
226 <!--- CONTEXT BAR -->
226 <!--- CONTEXT BAR -->
227 <div id="context-bar">
227 <div id="context-bar">
228 <div class="wrapper">
228 <div class="wrapper">
229 <ul id="context-pages" class="horizontal-list navigation">
229 <ul id="context-pages" class="horizontal-list navigation">
230 <li class="${is_active('summary')}"><a class="menulink" href="${h.url('summary_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
230 <li class="${is_active('summary')}"><a class="menulink" href="${h.url('summary_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
231 <li class="${is_active('changelog')}"><a class="menulink" href="${h.url('changelog_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
231 <li class="${is_active('changelog')}"><a class="menulink" href="${h.url('changelog_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
232 <li class="${is_active('files')}"><a class="menulink" href="${h.url('files_home', repo_name=c.repo_name, revision=c.rhodecode_db_repo.landing_rev[1])}"><div class="menulabel">${_('Files')}</div></a></li>
232 <li class="${is_active('files')}"><a class="menulink" href="${h.url('files_home', repo_name=c.repo_name, revision=c.rhodecode_db_repo.landing_rev[1])}"><div class="menulabel">${_('Files')}</div></a></li>
233 <li class="${is_active('compare')}">
233 <li class="${is_active('compare')}">
234 <a class="menulink" href="${h.url('compare_home',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a>
234 <a class="menulink" href="${h.url('compare_home',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a>
235 </li>
235 </li>
236 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
236 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
237 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
237 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
238 <li class="${is_active('showpullrequest')}">
238 <li class="${is_active('showpullrequest')}">
239 <a class="menulink" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}">
239 <a class="menulink" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}">
240 %if c.repository_pull_requests:
240 %if c.repository_pull_requests:
241 <span class="pr_notifications">${c.repository_pull_requests}</span>
241 <span class="pr_notifications">${c.repository_pull_requests}</span>
242 %endif
242 %endif
243 <div class="menulabel">${_('Pull Requests')}</div>
243 <div class="menulabel">${_('Pull Requests')}</div>
244 </a>
244 </a>
245 </li>
245 </li>
246 %endif
246 %endif
247 <li class="${is_active('options')}">
247 <li class="${is_active('options')}">
248 <a class="menulink" href="#" class="dropdown"><div class="menulabel">${_('Options')} <div class="show_more"></div></div></a>
248 <a class="menulink" href="#" class="dropdown"><div class="menulabel">${_('Options')} <div class="show_more"></div></div></a>
249 <ul class="submenu">
249 <ul class="submenu">
250 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
250 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
251 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}">${_('Settings')}</a></li>
251 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}">${_('Settings')}</a></li>
252 %endif
252 %endif
253 %if c.rhodecode_db_repo.fork:
253 %if c.rhodecode_db_repo.fork:
254 <li><a href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,source_ref_type=c.rhodecode_db_repo.landing_rev[0],source_ref=c.rhodecode_db_repo.landing_rev[1], target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1], merge=1)}">
254 <li><a href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,source_ref_type=c.rhodecode_db_repo.landing_rev[0],source_ref=c.rhodecode_db_repo.landing_rev[1], target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1], merge=1)}">
255 ${_('Compare fork')}</a></li>
255 ${_('Compare fork')}</a></li>
256 %endif
256 %endif
257
257
258 <li><a href="${h.url('search_repo_home',repo_name=c.repo_name)}">${_('Search')}</a></li>
258 <li><a href="${h.url('search_repo_home',repo_name=c.repo_name)}">${_('Search')}</a></li>
259
259
260 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
260 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
261 %if c.rhodecode_db_repo.locked[0]:
261 %if c.rhodecode_db_repo.locked[0]:
262 <li><a class="locking_del" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
262 <li><a class="locking_del" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
263 %else:
263 %else:
264 <li><a class="locking_add" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
264 <li><a class="locking_add" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
265 %endif
265 %endif
266 %endif
266 %endif
267 %if c.rhodecode_user.username != h.DEFAULT_USER:
267 %if c.rhodecode_user.username != h.DEFAULT_USER:
268 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
268 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
269 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}">${_('Fork')}</a></li>
269 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}">${_('Fork')}</a></li>
270 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
270 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
271 %endif
271 %endif
272 %endif
272 %endif
273 </ul>
273 </ul>
274 </li>
274 </li>
275 </ul>
275 </ul>
276 </div>
276 </div>
277 <div class="clear"></div>
277 <div class="clear"></div>
278 </div>
278 </div>
279 <!--- END CONTEXT BAR -->
279 <!--- END CONTEXT BAR -->
280
280
281 </%def>
281 </%def>
282
282
283 <%def name="usermenu()">
283 <%def name="usermenu()">
284 ## USER MENU
284 ## USER MENU
285 <li id="quick_login_li">
285 <li id="quick_login_li">
286 <a id="quick_login_link" class="menulink childs">
286 <a id="quick_login_link" class="menulink childs">
287 ${gravatar(c.rhodecode_user.email, 20)}
287 ${gravatar(c.rhodecode_user.email, 20)}
288 <span class="user">
288 <span class="user">
289 %if c.rhodecode_user.username != h.DEFAULT_USER:
289 %if c.rhodecode_user.username != h.DEFAULT_USER:
290 <span class="menu_link_user">${c.rhodecode_user.username}</span><div class="show_more"></div>
290 <span class="menu_link_user">${c.rhodecode_user.username}</span><div class="show_more"></div>
291 %else:
291 %else:
292 <span>${_('Sign in')}</span>
292 <span>${_('Sign in')}</span>
293 %endif
293 %endif
294 </span>
294 </span>
295 </a>
295 </a>
296
296
297 <div class="user-menu submenu">
297 <div class="user-menu submenu">
298 <div id="quick_login">
298 <div id="quick_login">
299 %if c.rhodecode_user.username == h.DEFAULT_USER:
299 %if c.rhodecode_user.username == h.DEFAULT_USER:
300 <h4>${_('Sign in to your account')}</h4>
300 <h4>${_('Sign in to your account')}</h4>
301 ${h.form(h.route_path('login', _query={'came_from': h.url.current()}), needs_csrf_token=False)}
301 ${h.form(h.route_path('login', _query={'came_from': h.url.current()}), needs_csrf_token=False)}
302 <div class="form form-vertical">
302 <div class="form form-vertical">
303 <div class="fields">
303 <div class="fields">
304 <div class="field">
304 <div class="field">
305 <div class="label">
305 <div class="label">
306 <label for="username">${_('Username')}:</label>
306 <label for="username">${_('Username')}:</label>
307 </div>
307 </div>
308 <div class="input">
308 <div class="input">
309 ${h.text('username',class_='focus',tabindex=1)}
309 ${h.text('username',class_='focus',tabindex=1)}
310 </div>
310 </div>
311
311
312 </div>
312 </div>
313 <div class="field">
313 <div class="field">
314 <div class="label">
314 <div class="label">
315 <label for="password">${_('Password')}:</label>
315 <label for="password">${_('Password')}:</label>
316 <span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'))}</span>
316 <span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'))}</span>
317 </div>
317 </div>
318 <div class="input">
318 <div class="input">
319 ${h.password('password',class_='focus',tabindex=2)}
319 ${h.password('password',class_='focus',tabindex=2)}
320 </div>
320 </div>
321 </div>
321 </div>
322 <div class="buttons">
322 <div class="buttons">
323 <div class="register">
323 <div class="register">
324 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
324 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
325 ${h.link_to(_("Don't have an account ?"),h.route_path('register'))}
325 ${h.link_to(_("Don't have an account ?"),h.route_path('register'))}
326 %endif
326 %endif
327 </div>
327 </div>
328 <div class="submit">
328 <div class="submit">
329 ${h.submit('sign_in',_('Sign In'),class_="btn btn-small",tabindex=3)}
329 ${h.submit('sign_in',_('Sign In'),class_="btn btn-small",tabindex=3)}
330 </div>
330 </div>
331 </div>
331 </div>
332 </div>
332 </div>
333 </div>
333 </div>
334 ${h.end_form()}
334 ${h.end_form()}
335 %else:
335 %else:
336 <div class="">
336 <div class="">
337 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
337 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
338 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
338 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
339 <div class="email">${c.rhodecode_user.email}</div>
339 <div class="email">${c.rhodecode_user.email}</div>
340 </div>
340 </div>
341 <div class="">
341 <div class="">
342 <ol class="links">
342 <ol class="links">
343 <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
343 <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
344 <li class="logout">
344 <li class="logout">
345 ${h.secure_form(h.route_path('logout'))}
345 ${h.secure_form(h.route_path('logout'))}
346 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
346 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
347 ${h.end_form()}
347 ${h.end_form()}
348 </li>
348 </li>
349 </ol>
349 </ol>
350 </div>
350 </div>
351 %endif
351 %endif
352 </div>
352 </div>
353 </div>
353 </div>
354 %if c.rhodecode_user.username != h.DEFAULT_USER:
354 %if c.rhodecode_user.username != h.DEFAULT_USER:
355 <div class="pill_container">
355 <div class="pill_container">
356 % if c.unread_notifications == 0:
356 % if c.unread_notifications == 0:
357 <a class="menu_link_notifications empty" href="${h.url('notifications')}">${c.unread_notifications}</a>
357 <a class="menu_link_notifications empty" href="${h.url('notifications')}">${c.unread_notifications}</a>
358 % else:
358 % else:
359 <a class="menu_link_notifications" href="${h.url('notifications')}">${c.unread_notifications}</a>
359 <a class="menu_link_notifications" href="${h.url('notifications')}">${c.unread_notifications}</a>
360 % endif
360 % endif
361 </div>
361 </div>
362 % endif
362 % endif
363 </li>
363 </li>
364 </%def>
364 </%def>
365
365
366 <%def name="menu_items(active=None)">
366 <%def name="menu_items(active=None)">
367 <%
367 <%
368 def is_active(selected):
368 def is_active(selected):
369 if selected == active:
369 if selected == active:
370 return "active"
370 return "active"
371 return ""
371 return ""
372 %>
372 %>
373 <ul id="quick" class="main_nav navigation horizontal-list">
373 <ul id="quick" class="main_nav navigation horizontal-list">
374 <!-- repo switcher -->
374 <!-- repo switcher -->
375 <li class="${is_active('repositories')} repo_switcher_li has_select2">
375 <li class="${is_active('repositories')} repo_switcher_li has_select2">
376 <input id="repo_switcher" name="repo_switcher" type="hidden">
376 <input id="repo_switcher" name="repo_switcher" type="hidden">
377 </li>
377 </li>
378
378
379 ## ROOT MENU
379 ## ROOT MENU
380 %if c.rhodecode_user.username != h.DEFAULT_USER:
380 %if c.rhodecode_user.username != h.DEFAULT_USER:
381 <li class="${is_active('journal')}">
381 <li class="${is_active('journal')}">
382 <a class="menulink" title="${_('Show activity journal')}" href="${h.url('journal')}">
382 <a class="menulink" title="${_('Show activity journal')}" href="${h.url('journal')}">
383 <div class="menulabel">${_('Journal')}</div>
383 <div class="menulabel">${_('Journal')}</div>
384 </a>
384 </a>
385 </li>
385 </li>
386 %else:
386 %else:
387 <li class="${is_active('journal')}">
387 <li class="${is_active('journal')}">
388 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.url('public_journal')}">
388 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.url('public_journal')}">
389 <div class="menulabel">${_('Public journal')}</div>
389 <div class="menulabel">${_('Public journal')}</div>
390 </a>
390 </a>
391 </li>
391 </li>
392 %endif
392 %endif
393 <li class="${is_active('gists')}">
393 <li class="${is_active('gists')}">
394 <a class="menulink childs" title="${_('Show Gists')}" href="${h.url('gists')}">
394 <a class="menulink childs" title="${_('Show Gists')}" href="${h.url('gists')}">
395 <div class="menulabel">${_('Gists')}</div>
395 <div class="menulabel">${_('Gists')}</div>
396 </a>
396 </a>
397 </li>
397 </li>
398 <li class="${is_active('search')}">
398 <li class="${is_active('search')}">
399 <a class="menulink" title="${_('Search in repositories you have access to')}" href="${h.url('search')}">
399 <a class="menulink" title="${_('Search in repositories you have access to')}" href="${h.url('search')}">
400 <div class="menulabel">${_('Search')}</div>
400 <div class="menulabel">${_('Search')}</div>
401 </a>
401 </a>
402 </li>
402 </li>
403 % if h.HasPermissionAll('hg.admin')('access admin main page'):
403 % if h.HasPermissionAll('hg.admin')('access admin main page'):
404 <li class="${is_active('admin')}">
404 <li class="${is_active('admin')}">
405 <a class="menulink childs" title="${_('Admin settings')}" href="#" onclick="return false;">
405 <a class="menulink childs" title="${_('Admin settings')}" href="#" onclick="return false;">
406 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
406 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
407 </a>
407 </a>
408 ${admin_menu()}
408 ${admin_menu()}
409 </li>
409 </li>
410 % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
410 % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
411 <li class="${is_active('admin')}">
411 <li class="${is_active('admin')}">
412 <a class="menulink childs" title="${_('Delegated Admin settings')}">
412 <a class="menulink childs" title="${_('Delegated Admin settings')}">
413 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
413 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
414 </a>
414 </a>
415 ${admin_menu_simple(c.rhodecode_user.repositories_admin,
415 ${admin_menu_simple(c.rhodecode_user.repositories_admin,
416 c.rhodecode_user.repository_groups_admin,
416 c.rhodecode_user.repository_groups_admin,
417 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
417 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
418 </li>
418 </li>
419 % endif
419 % endif
420 % if c.debug_style:
420 % if c.debug_style:
421 <li class="${is_active('debug_style')}">
421 <li class="${is_active('debug_style')}">
422 <a class="menulink" title="${_('Style')}" href="${h.url('debug_style_home')}">
422 <a class="menulink" title="${_('Style')}" href="${h.url('debug_style_home')}">
423 <div class="menulabel">${_('Style')}</div>
423 <div class="menulabel">${_('Style')}</div>
424 </a>
424 </a>
425 </li>
425 </li>
426 % endif
426 % endif
427 ## render extra user menu
427 ## render extra user menu
428 ${usermenu()}
428 ${usermenu()}
429 </ul>
429 </ul>
430
430
431 <script type="text/javascript">
431 <script type="text/javascript">
432 var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
432 var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
433
433
434 /*format the look of items in the list*/
434 /*format the look of items in the list*/
435 var format = function(state, escapeMarkup){
435 var format = function(state, escapeMarkup){
436 if (!state.id){
436 if (!state.id){
437 return state.text; // optgroup
437 return state.text; // optgroup
438 }
438 }
439 var obj_dict = state.obj;
439 var obj_dict = state.obj;
440 var tmpl = '';
440 var tmpl = '';
441
441
442 if(obj_dict && state.type == 'repo'){
442 if(obj_dict && state.type == 'repo'){
443 if(obj_dict['repo_type'] === 'hg'){
443 if(obj_dict['repo_type'] === 'hg'){
444 tmpl += '<i class="icon-hg"></i> ';
444 tmpl += '<i class="icon-hg"></i> ';
445 }
445 }
446 else if(obj_dict['repo_type'] === 'git'){
446 else if(obj_dict['repo_type'] === 'git'){
447 tmpl += '<i class="icon-git"></i> ';
447 tmpl += '<i class="icon-git"></i> ';
448 }
448 }
449 else if(obj_dict['repo_type'] === 'svn'){
449 else if(obj_dict['repo_type'] === 'svn'){
450 tmpl += '<i class="icon-svn"></i> ';
450 tmpl += '<i class="icon-svn"></i> ';
451 }
451 }
452 if(obj_dict['private']){
452 if(obj_dict['private']){
453 tmpl += '<i class="icon-lock" ></i> ';
453 tmpl += '<i class="icon-lock" ></i> ';
454 }
454 }
455 else if(visual_show_public_icon){
455 else if(visual_show_public_icon){
456 tmpl += '<i class="icon-unlock-alt"></i> ';
456 tmpl += '<i class="icon-unlock-alt"></i> ';
457 }
457 }
458 }
458 }
459 if(obj_dict && state.type == 'commit') {
459 if(obj_dict && state.type == 'commit') {
460 tmpl += '<i class="icon-tag"></i>';
460 tmpl += '<i class="icon-tag"></i>';
461 }
461 }
462 if(obj_dict && state.type == 'group'){
462 if(obj_dict && state.type == 'group'){
463 tmpl += '<i class="icon-folder-close"></i> ';
463 tmpl += '<i class="icon-folder-close"></i> ';
464 }
464 }
465 tmpl += escapeMarkup(state.text);
465 tmpl += escapeMarkup(state.text);
466 return tmpl;
466 return tmpl;
467 };
467 };
468
468
469 var formatResult = function(result, container, query, escapeMarkup) {
469 var formatResult = function(result, container, query, escapeMarkup) {
470 return format(result, escapeMarkup);
470 return format(result, escapeMarkup);
471 };
471 };
472
472
473 var formatSelection = function(data, container, escapeMarkup) {
473 var formatSelection = function(data, container, escapeMarkup) {
474 return format(data, escapeMarkup);
474 return format(data, escapeMarkup);
475 };
475 };
476
476
477 $("#repo_switcher").select2({
477 $("#repo_switcher").select2({
478 cachedDataSource: {},
478 cachedDataSource: {},
479 minimumInputLength: 2,
479 minimumInputLength: 2,
480 placeholder: '<div class="menulabel">${_('Go to')} <div class="show_more"></div></div>',
480 placeholder: '<div class="menulabel">${_('Go to')} <div class="show_more"></div></div>',
481 dropdownAutoWidth: true,
481 dropdownAutoWidth: true,
482 formatResult: formatResult,
482 formatResult: formatResult,
483 formatSelection: formatSelection,
483 formatSelection: formatSelection,
484 containerCssClass: "repo-switcher",
484 containerCssClass: "repo-switcher",
485 dropdownCssClass: "repo-switcher-dropdown",
485 dropdownCssClass: "repo-switcher-dropdown",
486 escapeMarkup: function(m){
486 escapeMarkup: function(m){
487 // don't escape our custom placeholder
487 // don't escape our custom placeholder
488 if(m.substr(0,23) == '<div class="menulabel">'){
488 if(m.substr(0,23) == '<div class="menulabel">'){
489 return m;
489 return m;
490 }
490 }
491
491
492 return Select2.util.escapeMarkup(m);
492 return Select2.util.escapeMarkup(m);
493 },
493 },
494 query: $.debounce(250, function(query){
494 query: $.debounce(250, function(query){
495 self = this;
495 self = this;
496 var cacheKey = query.term;
496 var cacheKey = query.term;
497 var cachedData = self.cachedDataSource[cacheKey];
497 var cachedData = self.cachedDataSource[cacheKey];
498
498
499 if (cachedData) {
499 if (cachedData) {
500 query.callback({results: cachedData.results});
500 query.callback({results: cachedData.results});
501 } else {
501 } else {
502 $.ajax({
502 $.ajax({
503 url: "${h.url('goto_switcher_data')}",
503 url: "${h.url('goto_switcher_data')}",
504 data: {'query': query.term},
504 data: {'query': query.term},
505 dataType: 'json',
505 dataType: 'json',
506 type: 'GET',
506 type: 'GET',
507 success: function(data) {
507 success: function(data) {
508 self.cachedDataSource[cacheKey] = data;
508 self.cachedDataSource[cacheKey] = data;
509 query.callback({results: data.results});
509 query.callback({results: data.results});
510 },
510 },
511 error: function(data, textStatus, errorThrown) {
511 error: function(data, textStatus, errorThrown) {
512 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
512 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
513 }
513 }
514 })
514 })
515 }
515 }
516 })
516 })
517 });
517 });
518
518
519 $("#repo_switcher").on('select2-selecting', function(e){
519 $("#repo_switcher").on('select2-selecting', function(e){
520 e.preventDefault();
520 e.preventDefault();
521 window.location = e.choice.url;
521 window.location = e.choice.url;
522 });
522 });
523
523
524 ## Global mouse bindings ##
524 ## Global mouse bindings ##
525
525
526 // general help "?"
526 // general help "?"
527 Mousetrap.bind(['?'], function(e) {
527 Mousetrap.bind(['?'], function(e) {
528 $('#help_kb').modal({})
528 $('#help_kb').modal({})
529 });
529 });
530
530
531 // / open the quick filter
531 // / open the quick filter
532 Mousetrap.bind(['/'], function(e) {
532 Mousetrap.bind(['/'], function(e) {
533 $("#repo_switcher").select2("open");
533 $("#repo_switcher").select2("open");
534
534
535 // return false to prevent default browser behavior
535 // return false to prevent default browser behavior
536 // and stop event from bubbling
536 // and stop event from bubbling
537 return false;
537 return false;
538 });
538 });
539
539
540 // general nav g + action
540 // general nav g + action
541 Mousetrap.bind(['g h'], function(e) {
541 Mousetrap.bind(['g h'], function(e) {
542 window.location = pyroutes.url('home');
542 window.location = pyroutes.url('home');
543 });
543 });
544 Mousetrap.bind(['g g'], function(e) {
544 Mousetrap.bind(['g g'], function(e) {
545 window.location = pyroutes.url('gists', {'private':1});
545 window.location = pyroutes.url('gists', {'private':1});
546 });
546 });
547 Mousetrap.bind(['g G'], function(e) {
547 Mousetrap.bind(['g G'], function(e) {
548 window.location = pyroutes.url('gists', {'public':1});
548 window.location = pyroutes.url('gists', {'public':1});
549 });
549 });
550 Mousetrap.bind(['n g'], function(e) {
550 Mousetrap.bind(['n g'], function(e) {
551 window.location = pyroutes.url('new_gist');
551 window.location = pyroutes.url('new_gist');
552 });
552 });
553 Mousetrap.bind(['n r'], function(e) {
553 Mousetrap.bind(['n r'], function(e) {
554 window.location = pyroutes.url('new_repo');
554 window.location = pyroutes.url('new_repo');
555 });
555 });
556
556
557 % if hasattr(c, 'repo_name') and hasattr(c, 'rhodecode_db_repo'):
557 % if hasattr(c, 'repo_name') and hasattr(c, 'rhodecode_db_repo'):
558 // nav in repo context
558 // nav in repo context
559 Mousetrap.bind(['g s'], function(e) {
559 Mousetrap.bind(['g s'], function(e) {
560 window.location = pyroutes.url('summary_home', {'repo_name': REPO_NAME});
560 window.location = pyroutes.url('summary_home', {'repo_name': REPO_NAME});
561 });
561 });
562 Mousetrap.bind(['g c'], function(e) {
562 Mousetrap.bind(['g c'], function(e) {
563 window.location = pyroutes.url('changelog_home', {'repo_name': REPO_NAME});
563 window.location = pyroutes.url('changelog_home', {'repo_name': REPO_NAME});
564 });
564 });
565 Mousetrap.bind(['g F'], function(e) {
565 Mousetrap.bind(['g F'], function(e) {
566 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': '', 'search': '1'});
566 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': '', 'search': '1'});
567 });
567 });
568 Mousetrap.bind(['g f'], function(e) {
568 Mousetrap.bind(['g f'], function(e) {
569 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': ''});
569 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': ''});
570 });
570 });
571 Mousetrap.bind(['g p'], function(e) {
571 Mousetrap.bind(['g p'], function(e) {
572 window.location = pyroutes.url('pullrequest_show_all', {'repo_name': REPO_NAME});
572 window.location = pyroutes.url('pullrequest_show_all', {'repo_name': REPO_NAME});
573 });
573 });
574 Mousetrap.bind(['g o'], function(e) {
574 Mousetrap.bind(['g o'], function(e) {
575 window.location = pyroutes.url('edit_repo', {'repo_name': REPO_NAME});
575 window.location = pyroutes.url('edit_repo', {'repo_name': REPO_NAME});
576 });
576 });
577 Mousetrap.bind(['g O'], function(e) {
577 Mousetrap.bind(['g O'], function(e) {
578 window.location = pyroutes.url('edit_repo_perms', {'repo_name': REPO_NAME});
578 window.location = pyroutes.url('edit_repo_perms', {'repo_name': REPO_NAME});
579 });
579 });
580 % endif
580 % endif
581
581
582 </script>
582 </script>
583 <script src="${h.url('/js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
583 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
584 </%def>
584 </%def>
585
585
586 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
586 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
587 <div class="modal-dialog">
587 <div class="modal-dialog">
588 <div class="modal-content">
588 <div class="modal-content">
589 <div class="modal-header">
589 <div class="modal-header">
590 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
590 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
591 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
591 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
592 </div>
592 </div>
593 <div class="modal-body">
593 <div class="modal-body">
594 <div class="block-left">
594 <div class="block-left">
595 <table class="keyboard-mappings">
595 <table class="keyboard-mappings">
596 <tbody>
596 <tbody>
597 <tr>
597 <tr>
598 <th></th>
598 <th></th>
599 <th>${_('Site-wide shortcuts')}</th>
599 <th>${_('Site-wide shortcuts')}</th>
600 </tr>
600 </tr>
601 <%
601 <%
602 elems = [
602 elems = [
603 ('/', 'Open quick search box'),
603 ('/', 'Open quick search box'),
604 ('g h', 'Goto home page'),
604 ('g h', 'Goto home page'),
605 ('g g', 'Goto my private gists page'),
605 ('g g', 'Goto my private gists page'),
606 ('g G', 'Goto my public gists page'),
606 ('g G', 'Goto my public gists page'),
607 ('n r', 'New repository page'),
607 ('n r', 'New repository page'),
608 ('n g', 'New gist page'),
608 ('n g', 'New gist page'),
609 ]
609 ]
610 %>
610 %>
611 %for key, desc in elems:
611 %for key, desc in elems:
612 <tr>
612 <tr>
613 <td class="keys">
613 <td class="keys">
614 <span class="key tag">${key}</span>
614 <span class="key tag">${key}</span>
615 </td>
615 </td>
616 <td>${desc}</td>
616 <td>${desc}</td>
617 </tr>
617 </tr>
618 %endfor
618 %endfor
619 </tbody>
619 </tbody>
620 </table>
620 </table>
621 </div>
621 </div>
622 <div class="block-left">
622 <div class="block-left">
623 <table class="keyboard-mappings">
623 <table class="keyboard-mappings">
624 <tbody>
624 <tbody>
625 <tr>
625 <tr>
626 <th></th>
626 <th></th>
627 <th>${_('Repositories')}</th>
627 <th>${_('Repositories')}</th>
628 </tr>
628 </tr>
629 <%
629 <%
630 elems = [
630 elems = [
631 ('g s', 'Goto summary page'),
631 ('g s', 'Goto summary page'),
632 ('g c', 'Goto changelog page'),
632 ('g c', 'Goto changelog page'),
633 ('g f', 'Goto files page'),
633 ('g f', 'Goto files page'),
634 ('g F', 'Goto files page with file search activated'),
634 ('g F', 'Goto files page with file search activated'),
635 ('g p', 'Goto pull requests page'),
635 ('g p', 'Goto pull requests page'),
636 ('g o', 'Goto repository settings'),
636 ('g o', 'Goto repository settings'),
637 ('g O', 'Goto repository permissions settings'),
637 ('g O', 'Goto repository permissions settings'),
638 ]
638 ]
639 %>
639 %>
640 %for key, desc in elems:
640 %for key, desc in elems:
641 <tr>
641 <tr>
642 <td class="keys">
642 <td class="keys">
643 <span class="key tag">${key}</span>
643 <span class="key tag">${key}</span>
644 </td>
644 </td>
645 <td>${desc}</td>
645 <td>${desc}</td>
646 </tr>
646 </tr>
647 %endfor
647 %endfor
648 </tbody>
648 </tbody>
649 </table>
649 </table>
650 </div>
650 </div>
651 </div>
651 </div>
652 <div class="modal-footer">
652 <div class="modal-footer">
653 </div>
653 </div>
654 </div><!-- /.modal-content -->
654 </div><!-- /.modal-content -->
655 </div><!-- /.modal-dialog -->
655 </div><!-- /.modal-dialog -->
656 </div><!-- /.modal -->
656 </div><!-- /.modal -->
@@ -1,135 +1,135 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html>
2 <!DOCTYPE html>
3
3
4 <%
4 <%
5 c.template_context['repo_name'] = getattr(c, 'repo_name', '')
5 c.template_context['repo_name'] = getattr(c, 'repo_name', '')
6
6
7 if hasattr(c, 'rhodecode_db_repo'):
7 if hasattr(c, 'rhodecode_db_repo'):
8 c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
8 c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
9 c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
9 c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
10
10
11 if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id:
11 if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id:
12 c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username
12 c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username
13 c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email
13 c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email
14
14
15 c.template_context['visual']['default_renderer'] = h.get_visual_attr(c, 'default_renderer')
15 c.template_context['visual']['default_renderer'] = h.get_visual_attr(c, 'default_renderer')
16 %>
16 %>
17
17
18 <html xmlns="http://www.w3.org/1999/xhtml">
18 <html xmlns="http://www.w3.org/1999/xhtml">
19 <head>
19 <head>
20 <title>${self.title()}</title>
20 <title>${self.title()}</title>
21 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
21 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
22 <%def name="robots()">
22 <%def name="robots()">
23 <meta name="robots" content="index, nofollow"/>
23 <meta name="robots" content="index, nofollow"/>
24 </%def>
24 </%def>
25 ${self.robots()}
25 ${self.robots()}
26 <link rel="icon" href="${h.url('/images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
26 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
27
27
28 ## CSS definitions
28 ## CSS definitions
29 <%def name="css()">
29 <%def name="css()">
30 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
30 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
31 <!--[if lt IE 9]>
31 <!--[if lt IE 9]>
32 <link rel="stylesheet" type="text/css" href="${h.url('/css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
32 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
33 <![endif]-->
33 <![endif]-->
34 ## EXTRA FOR CSS
34 ## EXTRA FOR CSS
35 ${self.css_extra()}
35 ${self.css_extra()}
36 </%def>
36 </%def>
37 ## CSS EXTRA - optionally inject some extra CSS stuff needed for specific websites
37 ## CSS EXTRA - optionally inject some extra CSS stuff needed for specific websites
38 <%def name="css_extra()">
38 <%def name="css_extra()">
39 </%def>
39 </%def>
40
40
41 ${self.css()}
41 ${self.css()}
42
42
43 ## JAVASCRIPT
43 ## JAVASCRIPT
44 <%def name="js()">
44 <%def name="js()">
45 <script src="${h.url('/js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
45 <script src="${h.asset('js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
46 <script type="text/javascript">
46 <script type="text/javascript">
47 // register templateContext to pass template variables to JS
47 // register templateContext to pass template variables to JS
48 var templateContext = ${h.json.dumps(c.template_context)|n};
48 var templateContext = ${h.json.dumps(c.template_context)|n};
49
49
50 var REPO_NAME = "${getattr(c, 'repo_name', '')}";
50 var REPO_NAME = "${getattr(c, 'repo_name', '')}";
51 %if hasattr(c, 'rhodecode_db_repo'):
51 %if hasattr(c, 'rhodecode_db_repo'):
52 var REPO_LANDING_REV = '${c.rhodecode_db_repo.landing_rev[1]}';
52 var REPO_LANDING_REV = '${c.rhodecode_db_repo.landing_rev[1]}';
53 var REPO_TYPE = '${c.rhodecode_db_repo.repo_type}';
53 var REPO_TYPE = '${c.rhodecode_db_repo.repo_type}';
54 %else:
54 %else:
55 var REPO_LANDING_REV = '';
55 var REPO_LANDING_REV = '';
56 var REPO_TYPE = '';
56 var REPO_TYPE = '';
57 %endif
57 %endif
58 var APPLICATION_URL = "${h.url('home').rstrip('/')}";
58 var APPLICATION_URL = "${h.url('home').rstrip('/')}";
59 var DEFAULT_RENDERER = "${h.get_visual_attr(c, 'default_renderer')}";
59 var DEFAULT_RENDERER = "${h.get_visual_attr(c, 'default_renderer')}";
60 var CSRF_TOKEN = "${getattr(c, 'csrf_token', '')}";
60 var CSRF_TOKEN = "${getattr(c, 'csrf_token', '')}";
61 % if getattr(c, 'rhodecode_user', None):
61 % if getattr(c, 'rhodecode_user', None):
62 var USER = {name:'${c.rhodecode_user.username}'};
62 var USER = {name:'${c.rhodecode_user.username}'};
63 % else:
63 % else:
64 var USER = {name:null};
64 var USER = {name:null};
65 % endif
65 % endif
66
66
67 var APPENLIGHT = {
67 var APPENLIGHT = {
68 enabled: ${'true' if getattr(c, 'appenlight_enabled', False) else 'false'},
68 enabled: ${'true' if getattr(c, 'appenlight_enabled', False) else 'false'},
69 key: '${getattr(c, "appenlight_api_public_key", "")}',
69 key: '${getattr(c, "appenlight_api_public_key", "")}',
70 serverUrl: '${getattr(c, "appenlight_server_url", "")}',
70 serverUrl: '${getattr(c, "appenlight_server_url", "")}',
71 requestInfo: {
71 requestInfo: {
72 % if getattr(c, 'rhodecode_user', None):
72 % if getattr(c, 'rhodecode_user', None):
73 ip: '${c.rhodecode_user.ip_addr}',
73 ip: '${c.rhodecode_user.ip_addr}',
74 username: '${c.rhodecode_user.username}'
74 username: '${c.rhodecode_user.username}'
75 % endif
75 % endif
76 }
76 }
77 };
77 };
78 </script>
78 </script>
79
79
80 <!--[if lt IE 9]>
80 <!--[if lt IE 9]>
81 <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
81 <script language="javascript" type="text/javascript" src="${h.asset('js/excanvas.min.js')}"></script>
82 <![endif]-->
82 <![endif]-->
83 <script language="javascript" type="text/javascript" src="${h.url('/js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
83 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
84 <script language="javascript" type="text/javascript" src="${h.url('/js/scripts.js', ver=c.rhodecode_version_hash)}"></script>
84 <script language="javascript" type="text/javascript" src="${h.asset('js/scripts.js', ver=c.rhodecode_version_hash)}"></script>
85 <script>CodeMirror.modeURL = "${h.url('/js/mode/%N/%N.js')}";</script>
85 <script>CodeMirror.modeURL = "${h.asset('js/mode/%N/%N.js')}";</script>
86
86
87 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
87 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
88 ${self.js_extra()}
88 ${self.js_extra()}
89
89
90 <script type="text/javascript">
90 <script type="text/javascript">
91 $(document).ready(function(){
91 $(document).ready(function(){
92 show_more_event();
92 show_more_event();
93 timeagoActivate();
93 timeagoActivate();
94 })
94 })
95 </script>
95 </script>
96
96
97 </%def>
97 </%def>
98
98
99 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
99 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
100 <%def name="js_extra()"></%def>
100 <%def name="js_extra()"></%def>
101 ${self.js()}
101 ${self.js()}
102
102
103 <%def name="head_extra()"></%def>
103 <%def name="head_extra()"></%def>
104 ${self.head_extra()}
104 ${self.head_extra()}
105
105
106 <%include file="/base/plugins_base.html"/>
106 <%include file="/base/plugins_base.html"/>
107
107
108 ## extra stuff
108 ## extra stuff
109 %if c.pre_code:
109 %if c.pre_code:
110 ${c.pre_code|n}
110 ${c.pre_code|n}
111 %endif
111 %endif
112 </head>
112 </head>
113 <body id="body">
113 <body id="body">
114 <noscript>
114 <noscript>
115 <div class="noscript-error">
115 <div class="noscript-error">
116 ${_('Please enable JavaScript to use RhodeCode Enterprise')}
116 ${_('Please enable JavaScript to use RhodeCode Enterprise')}
117 </div>
117 </div>
118 </noscript>
118 </noscript>
119 ## IE hacks
119 ## IE hacks
120 <!--[if IE 7]>
120 <!--[if IE 7]>
121 <script>$(document.body).addClass('ie7')</script>
121 <script>$(document.body).addClass('ie7')</script>
122 <![endif]-->
122 <![endif]-->
123 <!--[if IE 8]>
123 <!--[if IE 8]>
124 <script>$(document.body).addClass('ie8')</script>
124 <script>$(document.body).addClass('ie8')</script>
125 <![endif]-->
125 <![endif]-->
126 <!--[if IE 9]>
126 <!--[if IE 9]>
127 <script>$(document.body).addClass('ie9')</script>
127 <script>$(document.body).addClass('ie9')</script>
128 <![endif]-->
128 <![endif]-->
129
129
130 ${next.body()}
130 ${next.body()}
131 %if c.post_code:
131 %if c.post_code:
132 ${c.post_code|n}
132 ${c.post_code|n}
133 %endif
133 %endif
134 </body>
134 </body>
135 </html>
135 </html>
@@ -1,414 +1,414 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Changelog') % c.repo_name}
6 ${_('%s Changelog') % c.repo_name}
7 %if c.changelog_for_path:
7 %if c.changelog_for_path:
8 /${c.changelog_for_path}
8 /${c.changelog_for_path}
9 %endif
9 %endif
10 %if c.rhodecode_name:
10 %if c.rhodecode_name:
11 &middot; ${h.branding(c.rhodecode_name)}
11 &middot; ${h.branding(c.rhodecode_name)}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="breadcrumbs_links()">
15 <%def name="breadcrumbs_links()">
16 %if c.changelog_for_path:
16 %if c.changelog_for_path:
17 /${c.changelog_for_path}
17 /${c.changelog_for_path}
18 %endif
18 %endif
19 ${ungettext('showing %d out of %d commit', 'showing %d out of %d commits', c.showing_commits) % (c.showing_commits, c.total_cs)}
19 ${ungettext('showing %d out of %d commit', 'showing %d out of %d commits', c.showing_commits) % (c.showing_commits, c.total_cs)}
20 </%def>
20 </%def>
21
21
22 <%def name="menu_bar_nav()">
22 <%def name="menu_bar_nav()">
23 ${self.menu_items(active='repositories')}
23 ${self.menu_items(active='repositories')}
24 </%def>
24 </%def>
25
25
26 <%def name="menu_bar_subnav()">
26 <%def name="menu_bar_subnav()">
27 ${self.repo_menu(active='changelog')}
27 ${self.repo_menu(active='changelog')}
28 </%def>
28 </%def>
29
29
30 <%def name="main()">
30 <%def name="main()">
31
31
32 <div class="box">
32 <div class="box">
33 <div class="title">
33 <div class="title">
34 ${self.repo_page_title(c.rhodecode_db_repo)}
34 ${self.repo_page_title(c.rhodecode_db_repo)}
35 <ul class="links">
35 <ul class="links">
36 <li>
36 <li>
37 <a href="#" class="btn btn-small" id="rev_range_container" style="display:none;"></a>
37 <a href="#" class="btn btn-small" id="rev_range_container" style="display:none;"></a>
38 %if c.rhodecode_db_repo.fork:
38 %if c.rhodecode_db_repo.fork:
39 <span>
39 <span>
40 <a id="compare_fork_button"
40 <a id="compare_fork_button"
41 title="${_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}"
41 title="${_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}"
42 class="btn btn-small"
42 class="btn btn-small"
43 href="${h.url('compare_url',
43 href="${h.url('compare_url',
44 repo_name=c.rhodecode_db_repo.fork.repo_name,
44 repo_name=c.rhodecode_db_repo.fork.repo_name,
45 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
45 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
46 source_ref=c.rhodecode_db_repo.landing_rev[1],
46 source_ref=c.rhodecode_db_repo.landing_rev[1],
47 target_repo=c.repo_name,
47 target_repo=c.repo_name,
48 target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
48 target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
49 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
49 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
50 merge=1)
50 merge=1)
51 }">
51 }">
52 <i class="icon-loop"></i>
52 <i class="icon-loop"></i>
53 ${_('Compare fork with Parent (%s)' % c.rhodecode_db_repo.fork.repo_name)}
53 ${_('Compare fork with Parent (%s)' % c.rhodecode_db_repo.fork.repo_name)}
54 </a>
54 </a>
55 </span>
55 </span>
56 %endif
56 %endif
57
57
58 ## pr open link
58 ## pr open link
59 %if h.is_hg(c.rhodecode_repo) or h.is_git(c.rhodecode_repo):
59 %if h.is_hg(c.rhodecode_repo) or h.is_git(c.rhodecode_repo):
60 <span>
60 <span>
61 <a id="open_new_pull_request" class="btn btn-small btn-success" href="${h.url('pullrequest_home',repo_name=c.repo_name)}">
61 <a id="open_new_pull_request" class="btn btn-small btn-success" href="${h.url('pullrequest_home',repo_name=c.repo_name)}">
62 ${_('Open new pull request')}
62 ${_('Open new pull request')}
63 </a>
63 </a>
64 </span>
64 </span>
65 %endif
65 %endif
66
66
67 ## clear selection
67 ## clear selection
68 <div title="${_('Clear selection')}" class="btn" id="rev_range_clear" style="display:none">
68 <div title="${_('Clear selection')}" class="btn" id="rev_range_clear" style="display:none">
69 ${_('Clear selection')}
69 ${_('Clear selection')}
70 </div>
70 </div>
71
71
72 </li>
72 </li>
73 </ul>
73 </ul>
74 </div>
74 </div>
75
75
76 % if c.pagination:
76 % if c.pagination:
77
77
78 <div class="graph-header">
78 <div class="graph-header">
79 <div id="filter_changelog">
79 <div id="filter_changelog">
80 ${h.hidden('branch_filter')}
80 ${h.hidden('branch_filter')}
81 %if c.selected_name:
81 %if c.selected_name:
82 <div class="btn btn-default" id="clear_filter" >
82 <div class="btn btn-default" id="clear_filter" >
83 ${_('Clear filter')}
83 ${_('Clear filter')}
84 </div>
84 </div>
85 %endif
85 %endif
86 </div>
86 </div>
87 ${self.breadcrumbs('breadcrumbs_light')}
87 ${self.breadcrumbs('breadcrumbs_light')}
88 </div>
88 </div>
89
89
90 <div id="graph">
90 <div id="graph">
91 <div class="graph-col-wrapper">
91 <div class="graph-col-wrapper">
92 <div id="graph_nodes">
92 <div id="graph_nodes">
93 <div id="graph_canvas" data-graph='${c.jsdata|n}'></div>
93 <div id="graph_canvas" data-graph='${c.jsdata|n}'></div>
94 </div>
94 </div>
95 <div id="graph_content" class="main-content graph_full_width">
95 <div id="graph_content" class="main-content graph_full_width">
96
96
97 <div class="table">
97 <div class="table">
98 <table id="changesets" class="rctable">
98 <table id="changesets" class="rctable">
99 <tr>
99 <tr>
100 <th></th>
100 <th></th>
101 <th></th>
101 <th></th>
102 <th>${_('Author')}</th>
102 <th>${_('Author')}</th>
103 <th>${_('Age')}</th>
103 <th>${_('Age')}</th>
104 <th></th>
104 <th></th>
105 <th>${_('Commit Message')}</th>
105 <th>${_('Commit Message')}</th>
106 <th>${_('Commit')}</th>
106 <th>${_('Commit')}</th>
107 <th></th>
107 <th></th>
108 <th>${_('Refs')}</th>
108 <th>${_('Refs')}</th>
109 </tr>
109 </tr>
110 <tbody>
110 <tbody>
111 %for cnt,commit in enumerate(c.pagination):
111 %for cnt,commit in enumerate(c.pagination):
112 <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
112 <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
113
113
114 <td class="td-checkbox">
114 <td class="td-checkbox">
115 ${h.checkbox(commit.raw_id,class_="commit-range")}
115 ${h.checkbox(commit.raw_id,class_="commit-range")}
116 </td>
116 </td>
117 <td class="td-status">
117 <td class="td-status">
118
118
119 %if c.statuses.get(commit.raw_id):
119 %if c.statuses.get(commit.raw_id):
120 <div class="changeset-status-ico">
120 <div class="changeset-status-ico">
121 %if c.statuses.get(commit.raw_id)[2]:
121 %if c.statuses.get(commit.raw_id)[2]:
122 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
122 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
123 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
123 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
124 </a>
124 </a>
125 %else:
125 %else:
126 <a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
126 <a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
127 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
127 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
128 </a>
128 </a>
129 %endif
129 %endif
130 </div>
130 </div>
131 %endif
131 %endif
132 </td>
132 </td>
133 <td class="td-user">
133 <td class="td-user">
134 ${self.gravatar_with_user(commit.author)}
134 ${self.gravatar_with_user(commit.author)}
135 </td>
135 </td>
136 <td class="td-time">
136 <td class="td-time">
137 ${h.age_component(commit.date)}
137 ${h.age_component(commit.date)}
138 </td>
138 </td>
139
139
140 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}">
140 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}">
141 <div class="show_more_col">
141 <div class="show_more_col">
142 <i class="show_more"></i>&nbsp;
142 <i class="show_more"></i>&nbsp;
143 </div>
143 </div>
144 </td>
144 </td>
145 <td class="mid td-description">
145 <td class="mid td-description">
146 <div class="log-container truncate-wrap">
146 <div class="log-container truncate-wrap">
147 <div class="message truncate" id="c-${commit.raw_id}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
147 <div class="message truncate" id="c-${commit.raw_id}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
148 </div>
148 </div>
149 </td>
149 </td>
150
150
151 <td class="td-hash">
151 <td class="td-hash">
152 <code>
152 <code>
153 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
153 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
154 <span class="commit_hash">${h.show_id(commit)}</span>
154 <span class="commit_hash">${h.show_id(commit)}</span>
155 </a>
155 </a>
156 </code>
156 </code>
157 </td>
157 </td>
158
158
159 <td class="td-comments comments-col">
159 <td class="td-comments comments-col">
160 %if c.comments.get(commit.raw_id):
160 %if c.comments.get(commit.raw_id):
161 <a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
161 <a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
162 ${len(c.comments[commit.raw_id])} <i class="icon-comment icon-comment-colored"></i>
162 ${len(c.comments[commit.raw_id])} <i class="icon-comment icon-comment-colored"></i>
163 </a>
163 </a>
164 %endif
164 %endif
165 </td>
165 </td>
166
166
167 <td class="td-tags tags-col truncate-wrap">
167 <td class="td-tags tags-col truncate-wrap">
168 <div class="truncate tags-truncate" id="t-${commit.raw_id}">
168 <div class="truncate tags-truncate" id="t-${commit.raw_id}">
169 ## branch
169 ## branch
170 %if commit.branch:
170 %if commit.branch:
171 <span class="branchtag tag" title="${_('Branch %s') % commit.branch}">
171 <span class="branchtag tag" title="${_('Branch %s') % commit.branch}">
172 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
172 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
173 </span>
173 </span>
174 %endif
174 %endif
175
175
176 ## bookmarks
176 ## bookmarks
177 %if h.is_hg(c.rhodecode_repo):
177 %if h.is_hg(c.rhodecode_repo):
178 %for book in commit.bookmarks:
178 %for book in commit.bookmarks:
179 <span class="tag booktag" title="${_('Bookmark %s') % book}">
179 <span class="tag booktag" title="${_('Bookmark %s') % book}">
180 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
180 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
181 </span>
181 </span>
182 %endfor
182 %endfor
183 %endif
183 %endif
184
184
185 ## tags
185 ## tags
186 %for tag in commit.tags:
186 %for tag in commit.tags:
187 <span class="tagtag tag" title="${_('Tag %s') % tag}">
187 <span class="tagtag tag" title="${_('Tag %s') % tag}">
188 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
188 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
189 </span>
189 </span>
190 %endfor
190 %endfor
191
191
192 </div>
192 </div>
193 </td>
193 </td>
194 </tr>
194 </tr>
195 %endfor
195 %endfor
196 </tbody>
196 </tbody>
197 </table>
197 </table>
198 </div>
198 </div>
199 </div>
199 </div>
200 </div>
200 </div>
201 <div class="pagination-wh pagination-left">
201 <div class="pagination-wh pagination-left">
202 ${c.pagination.pager('$link_previous ~2~ $link_next')}
202 ${c.pagination.pager('$link_previous ~2~ $link_next')}
203 </div>
203 </div>
204
204
205 <script type="text/javascript" src="${h.url('/js/jquery.commits-graph.js')}"></script>
205 <script type="text/javascript" src="${h.asset('js/jquery.commits-graph.js')}"></script>
206 <script type="text/javascript">
206 <script type="text/javascript">
207 var cache = {};
207 var cache = {};
208 $(function(){
208 $(function(){
209
209
210 // Create links to commit ranges when range checkboxes are selected
210 // Create links to commit ranges when range checkboxes are selected
211 var $commitCheckboxes = $('.commit-range');
211 var $commitCheckboxes = $('.commit-range');
212 // cache elements
212 // cache elements
213 var $commitRangeContainer = $('#rev_range_container');
213 var $commitRangeContainer = $('#rev_range_container');
214 var $commitRangeClear = $('#rev_range_clear');
214 var $commitRangeClear = $('#rev_range_clear');
215
215
216 var checkboxRangeSelector = function(e){
216 var checkboxRangeSelector = function(e){
217 var selectedCheckboxes = [];
217 var selectedCheckboxes = [];
218 for (pos in $commitCheckboxes){
218 for (pos in $commitCheckboxes){
219 if($commitCheckboxes[pos].checked){
219 if($commitCheckboxes[pos].checked){
220 selectedCheckboxes.push($commitCheckboxes[pos]);
220 selectedCheckboxes.push($commitCheckboxes[pos]);
221 }
221 }
222 }
222 }
223 var open_new_pull_request = $('#open_new_pull_request');
223 var open_new_pull_request = $('#open_new_pull_request');
224 if(open_new_pull_request){
224 if(open_new_pull_request){
225 var selected_changes = selectedCheckboxes.length;
225 var selected_changes = selectedCheckboxes.length;
226 if (selected_changes > 1 || selected_changes == 1 && templateContext.repo_type != 'hg') {
226 if (selected_changes > 1 || selected_changes == 1 && templateContext.repo_type != 'hg') {
227 open_new_pull_request.hide();
227 open_new_pull_request.hide();
228 } else {
228 } else {
229 if (selected_changes == 1) {
229 if (selected_changes == 1) {
230 open_new_pull_request.html(_gettext('Open new pull request for selected commit'));
230 open_new_pull_request.html(_gettext('Open new pull request for selected commit'));
231 } else if (selected_changes == 0) {
231 } else if (selected_changes == 0) {
232 open_new_pull_request.html(_gettext('Open new pull request'));
232 open_new_pull_request.html(_gettext('Open new pull request'));
233 }
233 }
234 open_new_pull_request.show();
234 open_new_pull_request.show();
235 }
235 }
236 }
236 }
237
237
238 if (selectedCheckboxes.length>0){
238 if (selectedCheckboxes.length>0){
239 var revEnd = selectedCheckboxes[0].name;
239 var revEnd = selectedCheckboxes[0].name;
240 var revStart = selectedCheckboxes[selectedCheckboxes.length-1].name;
240 var revStart = selectedCheckboxes[selectedCheckboxes.length-1].name;
241 var url = pyroutes.url('changeset_home',
241 var url = pyroutes.url('changeset_home',
242 {'repo_name': '${c.repo_name}',
242 {'repo_name': '${c.repo_name}',
243 'revision': revStart+'...'+revEnd});
243 'revision': revStart+'...'+revEnd});
244
244
245 var link = (revStart == revEnd)
245 var link = (revStart == revEnd)
246 ? _gettext('Show selected commit __S')
246 ? _gettext('Show selected commit __S')
247 : _gettext('Show selected commits __S ... __E');
247 : _gettext('Show selected commits __S ... __E');
248
248
249 link = link.replace('__S', revStart.substr(0,6));
249 link = link.replace('__S', revStart.substr(0,6));
250 link = link.replace('__E', revEnd.substr(0,6));
250 link = link.replace('__E', revEnd.substr(0,6));
251
251
252 $commitRangeContainer
252 $commitRangeContainer
253 .attr('href',url)
253 .attr('href',url)
254 .html(link)
254 .html(link)
255 .show();
255 .show();
256
256
257 $commitRangeClear.show();
257 $commitRangeClear.show();
258 var _url = pyroutes.url('pullrequest_home',
258 var _url = pyroutes.url('pullrequest_home',
259 {'repo_name': '${c.repo_name}',
259 {'repo_name': '${c.repo_name}',
260 'commit': revEnd});
260 'commit': revEnd});
261 open_new_pull_request.attr('href', _url);
261 open_new_pull_request.attr('href', _url);
262 $('#compare_fork_button').hide();
262 $('#compare_fork_button').hide();
263 } else {
263 } else {
264 $commitRangeContainer.hide();
264 $commitRangeContainer.hide();
265 $commitRangeClear.hide();
265 $commitRangeClear.hide();
266
266
267 %if c.branch_name:
267 %if c.branch_name:
268 var _url = pyroutes.url('pullrequest_home',
268 var _url = pyroutes.url('pullrequest_home',
269 {'repo_name': '${c.repo_name}',
269 {'repo_name': '${c.repo_name}',
270 'branch':'${c.branch_name}'});
270 'branch':'${c.branch_name}'});
271 open_new_pull_request.attr('href', _url);
271 open_new_pull_request.attr('href', _url);
272 %else:
272 %else:
273 var _url = pyroutes.url('pullrequest_home',
273 var _url = pyroutes.url('pullrequest_home',
274 {'repo_name': '${c.repo_name}'});
274 {'repo_name': '${c.repo_name}'});
275 open_new_pull_request.attr('href', _url);
275 open_new_pull_request.attr('href', _url);
276 %endif
276 %endif
277 $('#compare_fork_button').show();
277 $('#compare_fork_button').show();
278 }
278 }
279 };
279 };
280
280
281 $commitCheckboxes.on('click', checkboxRangeSelector);
281 $commitCheckboxes.on('click', checkboxRangeSelector);
282
282
283 $commitRangeClear.on('click',function(e) {
283 $commitRangeClear.on('click',function(e) {
284 $commitCheckboxes.attr('checked', false)
284 $commitCheckboxes.attr('checked', false)
285 checkboxRangeSelector();
285 checkboxRangeSelector();
286 e.preventDefault();
286 e.preventDefault();
287 });
287 });
288
288
289 // make sure the buttons are consistent when navigate back and forth
289 // make sure the buttons are consistent when navigate back and forth
290 checkboxRangeSelector();
290 checkboxRangeSelector();
291
291
292
292
293 var msgs = $('.message');
293 var msgs = $('.message');
294 // get first element height
294 // get first element height
295 var el = $('#graph_content .container')[0];
295 var el = $('#graph_content .container')[0];
296 var row_h = el.clientHeight;
296 var row_h = el.clientHeight;
297 for (var i=0; i < msgs.length; i++) {
297 for (var i=0; i < msgs.length; i++) {
298 var m = msgs[i];
298 var m = msgs[i];
299
299
300 var h = m.clientHeight;
300 var h = m.clientHeight;
301 var pad = $(m).css('padding');
301 var pad = $(m).css('padding');
302 if (h > row_h) {
302 if (h > row_h) {
303 var offset = row_h - (h+12);
303 var offset = row_h - (h+12);
304 $(m.nextElementSibling).css('display','block');
304 $(m.nextElementSibling).css('display','block');
305 $(m.nextElementSibling).css('margin-top',offset+'px');
305 $(m.nextElementSibling).css('margin-top',offset+'px');
306 }
306 }
307 }
307 }
308
308
309 $('.expand_commit').on('click',function(e){
309 $('.expand_commit').on('click',function(e){
310 var target_expand = $(this);
310 var target_expand = $(this);
311 var cid = target_expand.data('commitId');
311 var cid = target_expand.data('commitId');
312
312
313 if (target_expand.hasClass('open')){
313 if (target_expand.hasClass('open')){
314 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
314 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
315 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
315 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
316 target_expand.removeClass('open');
316 target_expand.removeClass('open');
317 }
317 }
318 else {
318 else {
319 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
319 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
320 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
320 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
321 target_expand.addClass('open');
321 target_expand.addClass('open');
322 }
322 }
323 // redraw the graph
323 // redraw the graph
324 graph_options.height = $("#changesets").height();
324 graph_options.height = $("#changesets").height();
325 $("canvas").remove();
325 $("canvas").remove();
326 $("[data-graph]").commits(graph_options);
326 $("[data-graph]").commits(graph_options);
327 });
327 });
328
328
329 $("#clear_filter").on("click", function() {
329 $("#clear_filter").on("click", function() {
330 var filter = {'repo_name': '${c.repo_name}'};
330 var filter = {'repo_name': '${c.repo_name}'};
331 window.location = pyroutes.url('changelog_home', filter);
331 window.location = pyroutes.url('changelog_home', filter);
332 });
332 });
333
333
334 $("#branch_filter").select2({
334 $("#branch_filter").select2({
335 'dropdownAutoWidth': true,
335 'dropdownAutoWidth': true,
336 'width': 'resolve',
336 'width': 'resolve',
337 'placeholder': "${c.selected_name or _('Filter changelog')}",
337 'placeholder': "${c.selected_name or _('Filter changelog')}",
338 containerCssClass: "drop-menu",
338 containerCssClass: "drop-menu",
339 dropdownCssClass: "drop-menu-dropdown",
339 dropdownCssClass: "drop-menu-dropdown",
340 query: function(query){
340 query: function(query){
341 var key = 'cache';
341 var key = 'cache';
342 var cached = cache[key] ;
342 var cached = cache[key] ;
343 if(cached) {
343 if(cached) {
344 var data = {results: []};
344 var data = {results: []};
345 //filter results
345 //filter results
346 $.each(cached.results, function(){
346 $.each(cached.results, function(){
347 var section = this.text;
347 var section = this.text;
348 var children = [];
348 var children = [];
349 $.each(this.children, function(){
349 $.each(this.children, function(){
350 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
350 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
351 children.push({'id': this.id, 'text': this.text, 'type': this.type})
351 children.push({'id': this.id, 'text': this.text, 'type': this.type})
352 }
352 }
353 });
353 });
354 data.results.push({'text': section, 'children': children});
354 data.results.push({'text': section, 'children': children});
355 query.callback({results: data.results});
355 query.callback({results: data.results});
356 });
356 });
357 }else{
357 }else{
358 $.ajax({
358 $.ajax({
359 url: pyroutes.url('repo_refs_changelog_data', {'repo_name': '${c.repo_name}'}),
359 url: pyroutes.url('repo_refs_changelog_data', {'repo_name': '${c.repo_name}'}),
360 data: {},
360 data: {},
361 dataType: 'json',
361 dataType: 'json',
362 type: 'GET',
362 type: 'GET',
363 success: function(data) {
363 success: function(data) {
364 cache[key] = data;
364 cache[key] = data;
365 query.callback({results: data.results});
365 query.callback({results: data.results});
366 }
366 }
367 })
367 })
368 }
368 }
369 }
369 }
370 });
370 });
371
371
372 $('#branch_filter').on('change', function(e){
372 $('#branch_filter').on('change', function(e){
373 var data = $('#branch_filter').select2('data');
373 var data = $('#branch_filter').select2('data');
374 var selected = data.text;
374 var selected = data.text;
375 var filter = {'repo_name': '${c.repo_name}'};
375 var filter = {'repo_name': '${c.repo_name}'};
376 if(data.type == 'branch' || data.type == 'branch_closed'){
376 if(data.type == 'branch' || data.type == 'branch_closed'){
377 filter["branch"] = selected;
377 filter["branch"] = selected;
378 }
378 }
379 else if (data.type == 'book'){
379 else if (data.type == 'book'){
380 filter["bookmark"] = selected;
380 filter["bookmark"] = selected;
381 }
381 }
382 window.location = pyroutes.url('changelog_home', filter);
382 window.location = pyroutes.url('changelog_home', filter);
383 });
383 });
384
384
385 // Determine max number of edges per row in graph
385 // Determine max number of edges per row in graph
386 var jsdata = $.parseJSON($("[data-graph]").attr('data-graph'));
386 var jsdata = $.parseJSON($("[data-graph]").attr('data-graph'));
387 var edgeCount = 1;
387 var edgeCount = 1;
388 $.each(jsdata, function(i, item){
388 $.each(jsdata, function(i, item){
389 $.each(item[2], function(key, value) {
389 $.each(item[2], function(key, value) {
390 if (value[1] > edgeCount){
390 if (value[1] > edgeCount){
391 edgeCount = value[1];
391 edgeCount = value[1];
392 }
392 }
393 });
393 });
394 });
394 });
395 var x_step = Math.min(18, Math.floor(86 / edgeCount));
395 var x_step = Math.min(18, Math.floor(86 / edgeCount));
396 var graph_options = {
396 var graph_options = {
397 width: 100,
397 width: 100,
398 height: $("#changesets").height(),
398 height: $("#changesets").height(),
399 x_step: x_step,
399 x_step: x_step,
400 y_step: 42,
400 y_step: 42,
401 dotRadius: 3.5,
401 dotRadius: 3.5,
402 lineWidth: 2.5
402 lineWidth: 2.5
403 };
403 };
404 $("[data-graph]").commits(graph_options);
404 $("[data-graph]").commits(graph_options);
405
405
406 });
406 });
407
407
408 </script>
408 </script>
409 %else:
409 %else:
410 ${_('There are no changes yet')}
410 ${_('There are no changes yet')}
411 %endif
411 %endif
412 </div>
412 </div>
413 </div>
413 </div>
414 </%def>
414 </%def>
@@ -1,1162 +1,1162 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%namespace name="base" file="/base/base.html"/>
2 <%namespace name="base" file="/base/base.html"/>
3 <%inherit file="/debug_style/index.html"/>
3 <%inherit file="/debug_style/index.html"/>
4
4
5 <%def name="breadcrumbs_links()">
5 <%def name="breadcrumbs_links()">
6 ${h.link_to(_('Style'), h.url('debug_style_home'))}
6 ${h.link_to(_('Style'), h.url('debug_style_home'))}
7 &raquo;
7 &raquo;
8 ${c.active}
8 ${c.active}
9 </%def>
9 </%def>
10
10
11 <%def name="js_extra()">
11 <%def name="js_extra()">
12 <script type="text/javascript" src="${h.url('/js/mergerly.js')}"></script>
12 <script type="text/javascript" src="${h.asset('js/mergerly.js')}"></script>
13 </%def>
13 </%def>
14
14
15 <%def name="css_extra()">
15 <%def name="css_extra()">
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergerly.css')}"/>
16 <link rel="stylesheet" type="text/css" href="${h.asset('css/mergerly.css')}"/>
17 </%def>
17 </%def>
18
18
19
19
20 <%def name="real_main()">
20 <%def name="real_main()">
21 <div class="box">
21 <div class="box">
22 <div class="title">
22 <div class="title">
23 ${self.breadcrumbs()}
23 ${self.breadcrumbs()}
24 </div>
24 </div>
25
25
26 ##main
26 ##main
27 <div class='sidebar-col-wrapper'>
27 <div class='sidebar-col-wrapper'>
28 ${self.sidebar()}
28 ${self.sidebar()}
29
29
30 <div class="main-content">
30 <div class="main-content">
31
31
32
32
33
33
34 <h2>Code Blocks</h2>
34 <h2>Code Blocks</h2>
35
35
36 <dl class="dl-horizontal">
36 <dl class="dl-horizontal">
37 <dt><code>.codeblock</code></dt>
37 <dt><code>.codeblock</code></dt>
38 <dd>Used as a wrapping element around <code>.code-header</code> and
38 <dd>Used as a wrapping element around <code>.code-header</code> and
39 <code>.code-body</code>. Used to show the content of a file or a
39 <code>.code-body</code>. Used to show the content of a file or a
40 Gist.</dd>
40 Gist.</dd>
41
41
42 <dt><code>.diffblock</code></dt>
42 <dt><code>.diffblock</code></dt>
43 <dd>Used as a wrapping element to show a diff in a Commit or Pull
43 <dd>Used as a wrapping element to show a diff in a Commit or Pull
44 Request page. Contains usually <code>.code-header</code>,
44 Request page. Contains usually <code>.code-header</code>,
45 <code>.code-body</code> and in the edit case a <code>.message</code>.
45 <code>.code-body</code> and in the edit case a <code>.message</code>.
46 </dd>
46 </dd>
47 </dl>
47 </dl>
48
48
49
49
50 <p>Code Blocks are used in the following areas:</p>
50 <p>Code Blocks are used in the following areas:</p>
51
51
52 <ul>
52 <ul>
53 <li>Commit: Showing the Diff (still called Changeset in a few
53 <li>Commit: Showing the Diff (still called Changeset in a few
54 places).</li>
54 places).</li>
55 <li>File: Display a file, annotations, and edit a file.</li>
55 <li>File: Display a file, annotations, and edit a file.</li>
56 <li>Gist: Show the Gist and edit it.</li>
56 <li>Gist: Show the Gist and edit it.</li>
57 <li>Pull Request: Display the Diff of a Pull Request.</li>
57 <li>Pull Request: Display the Diff of a Pull Request.</li>
58 </ul>
58 </ul>
59
59
60
60
61
61
62 <!--
62 <!--
63 Compare Commits
63 Compare Commits
64 -->
64 -->
65 <h2>Compare Commits</h2>
65 <h2>Compare Commits</h2>
66
66
67 <div id="c-e589e34d6be8-5ab783e6d81b" class="diffblock margined comm">
67 <div id="c-e589e34d6be8-5ab783e6d81b" class="diffblock margined comm">
68 <div class="code-header">
68 <div class="code-header">
69 <div title="Go back to changed files overview">
69 <div title="Go back to changed files overview">
70 <a href="#changes_box">
70 <a href="#changes_box">
71 <i class="icon-circle-arrow-up"></i>
71 <i class="icon-circle-arrow-up"></i>
72 </a>
72 </a>
73 </div>
73 </div>
74 <div class="changeset_header">
74 <div class="changeset_header">
75 <div class="changeset_file">
75 <div class="changeset_file">
76 <i class="icon-file"></i>
76 <i class="icon-file"></i>
77 <a href="/example/files/e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d/rhodecode/public/css/code-block.less">rhodecode/public/css/code-block.less</a>
77 <a href="/example/files/e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d/rhodecode/public/css/code-block.less">rhodecode/public/css/code-block.less</a>
78 </div>
78 </div>
79 <div class="diff-actions">
79 <div class="diff-actions">
80 <a href="/example/diff/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full diff for this file">
80 <a href="/example/diff/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full diff for this file">
81 <img class="icon" src="/images/icons/page_white_go.png">
81 <img class="icon" src="/images/icons/page_white_go.png">
82 </a>
82 </a>
83 <a href="/example/diff-2way/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full side-by-side diff for this file">
83 <a href="/example/diff-2way/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full side-by-side diff for this file">
84 <img class="icon" src="/images/icons/application_double.png">
84 <img class="icon" src="/images/icons/application_double.png">
85 </a>
85 </a>
86 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=raw&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Raw diff" tt_title="Raw diff">
86 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=raw&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Raw diff" tt_title="Raw diff">
87 <img class="icon" src="/images/icons/page_white.png">
87 <img class="icon" src="/images/icons/page_white.png">
88 </a>
88 </a>
89 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=download&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Download diff">
89 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=download&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Download diff">
90 <img class="icon" src="/images/icons/page_save.png">
90 <img class="icon" src="/images/icons/page_save.png">
91 </a>
91 </a>
92 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=WS%3A1&amp;c-e589e34d6be8-5ab783e6d81b=C%3A3#c-e589e34d6be8-5ab783e6d81b" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
92 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=WS%3A1&amp;c-e589e34d6be8-5ab783e6d81b=C%3A3#c-e589e34d6be8-5ab783e6d81b" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
93 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=C%3A6#c-e589e34d6be8-5ab783e6d81b" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
93 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=C%3A6#c-e589e34d6be8-5ab783e6d81b" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
94 </div>
94 </div>
95 <span>
95 <span>
96 <label>
96 <label>
97 Show inline comments
97 Show inline comments
98 <input checked="checked" class="show-inline-comments" id="" id_for="c-e589e34d6be8-5ab783e6d81b" name="" type="checkbox" value="1">
98 <input checked="checked" class="show-inline-comments" id="" id_for="c-e589e34d6be8-5ab783e6d81b" name="" type="checkbox" value="1">
99 </label>
99 </label>
100 </span>
100 </span>
101 </div>
101 </div>
102 </div>
102 </div>
103 <div class="code-body">
103 <div class="code-body">
104 <div class="full_f_path" path="rhodecode/public/css/code-block.less"></div>
104 <div class="full_f_path" path="rhodecode/public/css/code-block.less"></div>
105 <table class="code-difftable">
105 <table class="code-difftable">
106 <tbody><tr class="line context">
106 <tbody><tr class="line context">
107 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
107 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
108 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
108 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
109 <td class="code no-comment">
109 <td class="code no-comment">
110 <pre>@@ -391,7 +391,7 @@
110 <pre>@@ -391,7 +391,7 @@
111 </pre>
111 </pre>
112 </td>
112 </td>
113 </tr>
113 </tr>
114 <tr class="line unmod">
114 <tr class="line unmod">
115 <td id="rhodecodepubliccsscode-blockless_o391" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o391">391</a></td>
115 <td id="rhodecodepubliccsscode-blockless_o391" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o391">391</a></td>
116 <td id="rhodecodepubliccsscode-blockless_n391" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n391">391</a></td>
116 <td id="rhodecodepubliccsscode-blockless_n391" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n391">391</a></td>
117 <td class="code no-comment">
117 <td class="code no-comment">
118 <pre>} /* Existing line, it might have a quite long content actually and in this case we might need some horizontal scrolling. The remaining text here is just used to make this line very long.
118 <pre>} /* Existing line, it might have a quite long content actually and in this case we might need some horizontal scrolling. The remaining text here is just used to make this line very long.
119 </pre>
119 </pre>
120 </td>
120 </td>
121 </tr>
121 </tr>
122 <tr class="line unmod">
122 <tr class="line unmod">
123 <td id="rhodecodepubliccsscode-blockless_o392" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o392">392</a></td>
123 <td id="rhodecodepubliccsscode-blockless_o392" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o392">392</a></td>
124 <td id="rhodecodepubliccsscode-blockless_n392" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n392">392</a></td>
124 <td id="rhodecodepubliccsscode-blockless_n392" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n392">392</a></td>
125 <td class="code no-comment">
125 <td class="code no-comment">
126 <pre></pre>
126 <pre></pre>
127 </td>
127 </td>
128 </tr>
128 </tr>
129 <tr class="line unmod">
129 <tr class="line unmod">
130 <td id="rhodecodepubliccsscode-blockless_o393" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o393">393</a></td>
130 <td id="rhodecodepubliccsscode-blockless_o393" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o393">393</a></td>
131 <td id="rhodecodepubliccsscode-blockless_n393" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n393">393</a></td>
131 <td id="rhodecodepubliccsscode-blockless_n393" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n393">393</a></td>
132 <td class="code no-comment">
132 <td class="code no-comment">
133 <pre>.code-body.textarea.editor,
133 <pre>.code-body.textarea.editor,
134 </pre>
134 </pre>
135 </td>
135 </td>
136 </tr>
136 </tr>
137 <tr class="line del">
137 <tr class="line del">
138 <td id="rhodecodepubliccsscode-blockless_o394" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o394">394</a></td>
138 <td id="rhodecodepubliccsscode-blockless_o394" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o394">394</a></td>
139 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n"></a></td>
139 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n"></a></td>
140 <td class="code no-comment">
140 <td class="code no-comment">
141 <pre>div.code-body{
141 <pre>div.code-body{
142 </pre>
142 </pre>
143 </td>
143 </td>
144 </tr>
144 </tr>
145 <tr class="line add">
145 <tr class="line add">
146 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
146 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
147 <td id="rhodecodepubliccsscode-blockless_n394" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n394">394</a></td>
147 <td id="rhodecodepubliccsscode-blockless_n394" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n394">394</a></td>
148 <td class="code no-comment">
148 <td class="code no-comment">
149 <pre>div.code-body<ins> </ins>{
149 <pre>div.code-body<ins> </ins>{
150 </pre>
150 </pre>
151 </td>
151 </td>
152 </tr>
152 </tr>
153 <tr class="line unmod">
153 <tr class="line unmod">
154 <td id="rhodecodepubliccsscode-blockless_o395" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o395">395</a></td>
154 <td id="rhodecodepubliccsscode-blockless_o395" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o395">395</a></td>
155 <td id="rhodecodepubliccsscode-blockless_n395" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n395">395</a></td>
155 <td id="rhodecodepubliccsscode-blockless_n395" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n395">395</a></td>
156 <td class="code no-comment">
156 <td class="code no-comment">
157 <pre> float: left;
157 <pre> float: left;
158 </pre>
158 </pre>
159 </td>
159 </td>
160 </tr>
160 </tr>
161 <tr class="line unmod">
161 <tr class="line unmod">
162 <td id="rhodecodepubliccsscode-blockless_o396" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o396">396</a></td>
162 <td id="rhodecodepubliccsscode-blockless_o396" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o396">396</a></td>
163 <td id="rhodecodepubliccsscode-blockless_n396" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n396">396</a></td>
163 <td id="rhodecodepubliccsscode-blockless_n396" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n396">396</a></td>
164 <td class="code no-comment">
164 <td class="code no-comment">
165 <pre> position: relative;
165 <pre> position: relative;
166 </pre>
166 </pre>
167 </td>
167 </td>
168 </tr>
168 </tr>
169 <tr class="line unmod">
169 <tr class="line unmod">
170 <td id="rhodecodepubliccsscode-blockless_o397" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o397">397</a></td>
170 <td id="rhodecodepubliccsscode-blockless_o397" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o397">397</a></td>
171 <td id="rhodecodepubliccsscode-blockless_n397" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n397">397</a></td>
171 <td id="rhodecodepubliccsscode-blockless_n397" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n397">397</a></td>
172 <td class="code no-comment">
172 <td class="code no-comment">
173 <pre> max-width: none;
173 <pre> max-width: none;
174 </pre>
174 </pre>
175 </td>
175 </td>
176 </tr>
176 </tr>
177 <tr class="line context">
177 <tr class="line context">
178 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
178 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
179 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
179 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
180 <td class="code no-comment">
180 <td class="code no-comment">
181 <pre>@@ -399,3 +399,6 @@
181 <pre>@@ -399,3 +399,6 @@
182 </pre>
182 </pre>
183 </td>
183 </td>
184 </tr>
184 </tr>
185 <tr class="line unmod">
185 <tr class="line unmod">
186 <td id="rhodecodepubliccsscode-blockless_o399" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o399">399</a></td>
186 <td id="rhodecodepubliccsscode-blockless_o399" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o399">399</a></td>
187 <td id="rhodecodepubliccsscode-blockless_n399" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n399">399</a></td>
187 <td id="rhodecodepubliccsscode-blockless_n399" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n399">399</a></td>
188 <td class="code no-comment">
188 <td class="code no-comment">
189 <pre> box-sizing: border-box;
189 <pre> box-sizing: border-box;
190 </pre>
190 </pre>
191 </td>
191 </td>
192 </tr>
192 </tr>
193 <tr class="line unmod">
193 <tr class="line unmod">
194 <td id="rhodecodepubliccsscode-blockless_o400" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o400">400</a></td>
194 <td id="rhodecodepubliccsscode-blockless_o400" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o400">400</a></td>
195 <td id="rhodecodepubliccsscode-blockless_n400" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n400">400</a></td>
195 <td id="rhodecodepubliccsscode-blockless_n400" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n400">400</a></td>
196 <td class="code no-comment">
196 <td class="code no-comment">
197 <pre>}
197 <pre>}
198 </pre>
198 </pre>
199 </td>
199 </td>
200 </tr>
200 </tr>
201 <tr class="line unmod">
201 <tr class="line unmod">
202 <td id="rhodecodepubliccsscode-blockless_o401" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o401">401</a></td>
202 <td id="rhodecodepubliccsscode-blockless_o401" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o401">401</a></td>
203 <td id="rhodecodepubliccsscode-blockless_n401" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n401">401</a></td>
203 <td id="rhodecodepubliccsscode-blockless_n401" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n401">401</a></td>
204 <td class="code no-comment">
204 <td class="code no-comment">
205 <pre></pre>
205 <pre></pre>
206 </td>
206 </td>
207 </tr>
207 </tr>
208 <tr class="line add">
208 <tr class="line add">
209 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
209 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
210 <td id="rhodecodepubliccsscode-blockless_n402" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n402">402</a></td>
210 <td id="rhodecodepubliccsscode-blockless_n402" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n402">402</a></td>
211 <td class="code no-comment">
211 <td class="code no-comment">
212 <pre>.code-body td{
212 <pre>.code-body td{
213 </pre>
213 </pre>
214 </td>
214 </td>
215 </tr>
215 </tr>
216 <tr class="line add">
216 <tr class="line add">
217 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
217 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
218 <td id="rhodecodepubliccsscode-blockless_n403" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n403">403</a></td>
218 <td id="rhodecodepubliccsscode-blockless_n403" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n403">403</a></td>
219 <td class="code no-comment">
219 <td class="code no-comment">
220 <pre> line-height: 1.2em;
220 <pre> line-height: 1.2em;
221 </pre>
221 </pre>
222 </td>
222 </td>
223 </tr>
223 </tr>
224 <tr class="line add">
224 <tr class="line add">
225 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
225 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
226 <td id="rhodecodepubliccsscode-blockless_n404" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n404">404</a></td>
226 <td id="rhodecodepubliccsscode-blockless_n404" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n404">404</a></td>
227 <td class="code no-comment">
227 <td class="code no-comment">
228 <pre>}
228 <pre>}
229 </pre>
229 </pre>
230 </td>
230 </td>
231 </tr>
231 </tr>
232 <tr class="line context">
232 <tr class="line context">
233 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
233 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
234 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
234 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
235 <td class="code no-comment">
235 <td class="code no-comment">
236 <pre> No newline at end of file
236 <pre> No newline at end of file
237 </pre>
237 </pre>
238 </td>
238 </td>
239 </tr>
239 </tr>
240 </tbody></table>
240 </tbody></table>
241 </div>
241 </div>
242 </div>
242 </div>
243
243
244
244
245
245
246
246
247
247
248
248
249 <!--
249 <!--
250 Pull Request
250 Pull Request
251 -->
251 -->
252
252
253 <h2>Pull Request</h2>
253 <h2>Pull Request</h2>
254
254
255 <div class="cs_files">
255 <div class="cs_files">
256 <table class="compare_view_files">
256 <table class="compare_view_files">
257
257
258 <tbody><tr class="cs_M collapse_file" fid="c--5f1d017cf13b">
258 <tbody><tr class="cs_M collapse_file" fid="c--5f1d017cf13b">
259 <td class="cs_icon_td">
259 <td class="cs_icon_td">
260 <span class="collapse_file_icon" fid="c--5f1d017cf13b"></span>
260 <span class="collapse_file_icon" fid="c--5f1d017cf13b"></span>
261 </td>
261 </td>
262 <td class="cs_icon_td">
262 <td class="cs_icon_td">
263 <div class="flag_status not_reviewed hidden"></div>
263 <div class="flag_status not_reviewed hidden"></div>
264 </td>
264 </td>
265 <td id="a_c--5f1d017cf13b">
265 <td id="a_c--5f1d017cf13b">
266 <a class="compare_view_filepath" href="#a_c--5f1d017cf13b">
266 <a class="compare_view_filepath" href="#a_c--5f1d017cf13b">
267 rhodecode/public/css/main.less
267 rhodecode/public/css/main.less
268 </a>
268 </a>
269 <span id="diff_c--5f1d017cf13b" class="diff_links" style="">
269 <span id="diff_c--5f1d017cf13b" class="diff_links" style="">
270 <a href="/example/diff/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
270 <a href="/example/diff/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
271 Unified Diff
271 Unified Diff
272 </a>
272 </a>
273 |
273 |
274 <a href="/example/diff-2way/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
274 <a href="/example/diff-2way/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
275 Side-by-side Diff
275 Side-by-side Diff
276 </a>
276 </a>
277 </span>
277 </span>
278 </td>
278 </td>
279 <td>
279 <td>
280 <div class="changes pull-right"><div style="width:100px"><div class="added top-left-rounded-corner-mid bottom-left-rounded-corner-mid" style="width:33.3333333333%">1</div><div class="deleted top-right-rounded-corner-mid bottom-right-rounded-corner-mid" style="width:66.6666666667%">2</div></div></div>
280 <div class="changes pull-right"><div style="width:100px"><div class="added top-left-rounded-corner-mid bottom-left-rounded-corner-mid" style="width:33.3333333333%">1</div><div class="deleted top-right-rounded-corner-mid bottom-right-rounded-corner-mid" style="width:66.6666666667%">2</div></div></div>
281 <div class="comment-bubble pull-right" data-path="rhodecode/public/css/main.less">
281 <div class="comment-bubble pull-right" data-path="rhodecode/public/css/main.less">
282 <i class="icon-comment"></i>
282 <i class="icon-comment"></i>
283 </div>
283 </div>
284 </td>
284 </td>
285 </tr>
285 </tr>
286 <tr id="tr_c--5f1d017cf13b">
286 <tr id="tr_c--5f1d017cf13b">
287 <td></td>
287 <td></td>
288 <td></td>
288 <td></td>
289 <td class="injected_diff" colspan="2">
289 <td class="injected_diff" colspan="2">
290
290
291 <div class="diff-container" id="diff-container-140360026534904">
291 <div class="diff-container" id="diff-container-140360026534904">
292 <div id="c--5f1d017cf13b_target"></div>
292 <div id="c--5f1d017cf13b_target"></div>
293 <div id="c--5f1d017cf13b" class="diffblock margined comm">
293 <div id="c--5f1d017cf13b" class="diffblock margined comm">
294 <div class="code-body">
294 <div class="code-body">
295 <div class="full_f_path" path="rhodecode/public/css/main.less" style="display: none;"></div>
295 <div class="full_f_path" path="rhodecode/public/css/main.less" style="display: none;"></div>
296 <table class="code-difftable">
296 <table class="code-difftable">
297 <tbody><tr class="line context">
297 <tbody><tr class="line context">
298 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
298 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
299 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
299 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
300 <td class="code ">
300 <td class="code ">
301 <pre>@@ -2110,7 +2110,6 @@
301 <pre>@@ -2110,7 +2110,6 @@
302 </pre>
302 </pre>
303 </td>
303 </td>
304 </tr>
304 </tr>
305 <tr class="line unmod">
305 <tr class="line unmod">
306 <td id="rhodecodepubliccssmainless_o2110" class="lineno old"><a href="#rhodecodepubliccssmainless_o2110">2110</a></td>
306 <td id="rhodecodepubliccssmainless_o2110" class="lineno old"><a href="#rhodecodepubliccssmainless_o2110">2110</a></td>
307 <td id="rhodecodepubliccssmainless_n2110" class="lineno new"><a href="#rhodecodepubliccssmainless_n2110">2110</a></td>
307 <td id="rhodecodepubliccssmainless_n2110" class="lineno new"><a href="#rhodecodepubliccssmainless_n2110">2110</a></td>
308 <td class="code ">
308 <td class="code ">
309 <pre><span class="tab-escape"> </span>width: auto !important;
309 <pre><span class="tab-escape"> </span>width: auto !important;
310 </pre>
310 </pre>
311 </td>
311 </td>
312 </tr>
312 </tr>
313 <tr class="line unmod">
313 <tr class="line unmod">
314 <td id="rhodecodepubliccssmainless_o2111" class="lineno old"><a href="#rhodecodepubliccssmainless_o2111">2111</a></td>
314 <td id="rhodecodepubliccssmainless_o2111" class="lineno old"><a href="#rhodecodepubliccssmainless_o2111">2111</a></td>
315 <td id="rhodecodepubliccssmainless_n2111" class="lineno new"><a href="#rhodecodepubliccssmainless_n2111">2111</a></td>
315 <td id="rhodecodepubliccssmainless_n2111" class="lineno new"><a href="#rhodecodepubliccssmainless_n2111">2111</a></td>
316 <td class="code ">
316 <td class="code ">
317 <pre><span class="tab-escape"> </span>min-width: 160px;
317 <pre><span class="tab-escape"> </span>min-width: 160px;
318 </pre>
318 </pre>
319 </td>
319 </td>
320 </tr>
320 </tr>
321 <tr class="line unmod">
321 <tr class="line unmod">
322 <td id="rhodecodepubliccssmainless_o2112" class="lineno old"><a href="#rhodecodepubliccssmainless_o2112">2112</a></td>
322 <td id="rhodecodepubliccssmainless_o2112" class="lineno old"><a href="#rhodecodepubliccssmainless_o2112">2112</a></td>
323 <td id="rhodecodepubliccssmainless_n2112" class="lineno new"><a href="#rhodecodepubliccssmainless_n2112">2112</a></td>
323 <td id="rhodecodepubliccssmainless_n2112" class="lineno new"><a href="#rhodecodepubliccssmainless_n2112">2112</a></td>
324 <td class="code ">
324 <td class="code ">
325 <pre><span class="tab-escape"> </span>margin: @padding @padding @padding 0;
325 <pre><span class="tab-escape"> </span>margin: @padding @padding @padding 0;
326 </pre>
326 </pre>
327 </td>
327 </td>
328 </tr>
328 </tr>
329 <tr class="line del">
329 <tr class="line del">
330 <td id="rhodecodepubliccssmainless_o2113" class="lineno old"><a href="#rhodecodepubliccssmainless_o2113">2113</a></td>
330 <td id="rhodecodepubliccssmainless_o2113" class="lineno old"><a href="#rhodecodepubliccssmainless_o2113">2113</a></td>
331 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
331 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
332 <td class="code ">
332 <td class="code ">
333 <pre><span class="tab-escape"> </span>padding: .9em; /* Old comment which was making this line a very long line so that we might have to deal with it by either adding horizontal scrolling or some smart way of breaking this line. */
333 <pre><span class="tab-escape"> </span>padding: .9em; /* Old comment which was making this line a very long line so that we might have to deal with it by either adding horizontal scrolling or some smart way of breaking this line. */
334 </pre>
334 </pre>
335 </td>
335 </td>
336 </tr>
336 </tr>
337 <tr class="line unmod">
337 <tr class="line unmod">
338 <td id="rhodecodepubliccssmainless_o2114" class="lineno old"><a href="#rhodecodepubliccssmainless_o2114">2114</a></td>
338 <td id="rhodecodepubliccssmainless_o2114" class="lineno old"><a href="#rhodecodepubliccssmainless_o2114">2114</a></td>
339 <td id="rhodecodepubliccssmainless_n2113" class="lineno new"><a href="#rhodecodepubliccssmainless_n2113">2113</a></td>
339 <td id="rhodecodepubliccssmainless_n2113" class="lineno new"><a href="#rhodecodepubliccssmainless_n2113">2113</a></td>
340 <td class="code ">
340 <td class="code ">
341 <pre> line-height: 1em;
341 <pre> line-height: 1em;
342 </pre>
342 </pre>
343 </td>
343 </td>
344 </tr>
344 </tr>
345 <tr class="line unmod">
345 <tr class="line unmod">
346 <td id="rhodecodepubliccssmainless_o2115" class="lineno old"><a href="#rhodecodepubliccssmainless_o2115">2115</a></td>
346 <td id="rhodecodepubliccssmainless_o2115" class="lineno old"><a href="#rhodecodepubliccssmainless_o2115">2115</a></td>
347 <td id="rhodecodepubliccssmainless_n2114" class="lineno new"><a href="#rhodecodepubliccssmainless_n2114">2114</a></td>
347 <td id="rhodecodepubliccssmainless_n2114" class="lineno new"><a href="#rhodecodepubliccssmainless_n2114">2114</a></td>
348 <td class="code ">
348 <td class="code ">
349 <pre><span class="tab-escape"> </span>z-index: 100;//js sets the menu below it to 9999
349 <pre><span class="tab-escape"> </span>z-index: 100;//js sets the menu below it to 9999
350 </pre>
350 </pre>
351 </td>
351 </td>
352 </tr>
352 </tr>
353 <tr class="line unmod">
353 <tr class="line unmod">
354 <td id="rhodecodepubliccssmainless_o2116" class="lineno old"><a href="#rhodecodepubliccssmainless_o2116">2116</a></td>
354 <td id="rhodecodepubliccssmainless_o2116" class="lineno old"><a href="#rhodecodepubliccssmainless_o2116">2116</a></td>
355 <td id="rhodecodepubliccssmainless_n2115" class="lineno new"><a href="#rhodecodepubliccssmainless_n2115">2115</a></td>
355 <td id="rhodecodepubliccssmainless_n2115" class="lineno new"><a href="#rhodecodepubliccssmainless_n2115">2115</a></td>
356 <td class="code ">
356 <td class="code ">
357 <pre><span class="tab-escape"> </span>background-color: white;
357 <pre><span class="tab-escape"> </span>background-color: white;
358 </pre>
358 </pre>
359 </td>
359 </td>
360 </tr>
360 </tr>
361 <tr class="line context">
361 <tr class="line context">
362 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
362 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
363 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
363 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
364 <td class="code ">
364 <td class="code ">
365 <pre>@@ -2118,7 +2117,7 @@
365 <pre>@@ -2118,7 +2117,7 @@
366 </pre>
366 </pre>
367 </td>
367 </td>
368 </tr>
368 </tr>
369 <tr class="line unmod">
369 <tr class="line unmod">
370 <td id="rhodecodepubliccssmainless_o2118" class="lineno old"><a href="#rhodecodepubliccssmainless_o2118">2118</a></td>
370 <td id="rhodecodepubliccssmainless_o2118" class="lineno old"><a href="#rhodecodepubliccssmainless_o2118">2118</a></td>
371 <td id="rhodecodepubliccssmainless_n2117" class="lineno new"><a href="#rhodecodepubliccssmainless_n2117">2117</a></td>
371 <td id="rhodecodepubliccssmainless_n2117" class="lineno new"><a href="#rhodecodepubliccssmainless_n2117">2117</a></td>
372 <td class="code ">
372 <td class="code ">
373 <pre></pre>
373 <pre></pre>
374 </td>
374 </td>
375 </tr>
375 </tr>
376 <tr class="line unmod">
376 <tr class="line unmod">
377 <td id="rhodecodepubliccssmainless_o2119" class="lineno old"><a href="#rhodecodepubliccssmainless_o2119">2119</a></td>
377 <td id="rhodecodepubliccssmainless_o2119" class="lineno old"><a href="#rhodecodepubliccssmainless_o2119">2119</a></td>
378 <td id="rhodecodepubliccssmainless_n2118" class="lineno new"><a href="#rhodecodepubliccssmainless_n2118">2118</a></td>
378 <td id="rhodecodepubliccssmainless_n2118" class="lineno new"><a href="#rhodecodepubliccssmainless_n2118">2118</a></td>
379 <td class="code ">
379 <td class="code ">
380 <pre><span class="tab-escape"> </span>a {
380 <pre><span class="tab-escape"> </span>a {
381 </pre>
381 </pre>
382 </td>
382 </td>
383 </tr>
383 </tr>
384 <tr class="line unmod">
384 <tr class="line unmod">
385 <td id="rhodecodepubliccssmainless_o2120" class="lineno old"><a href="#rhodecodepubliccssmainless_o2120">2120</a></td>
385 <td id="rhodecodepubliccssmainless_o2120" class="lineno old"><a href="#rhodecodepubliccssmainless_o2120">2120</a></td>
386 <td id="rhodecodepubliccssmainless_n2119" class="lineno new"><a href="#rhodecodepubliccssmainless_n2119">2119</a></td>
386 <td id="rhodecodepubliccssmainless_n2119" class="lineno new"><a href="#rhodecodepubliccssmainless_n2119">2119</a></td>
387 <td class="code ">
387 <td class="code ">
388 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>display:block;
388 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>display:block;
389 </pre>
389 </pre>
390 </td>
390 </td>
391 </tr>
391 </tr>
392 <tr class="line del">
392 <tr class="line del">
393 <td id="rhodecodepubliccssmainless_o2121" class="lineno old"><a href="#rhodecodepubliccssmainless_o2121">2121</a></td>
393 <td id="rhodecodepubliccssmainless_o2121" class="lineno old"><a href="#rhodecodepubliccssmainless_o2121">2121</a></td>
394 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
394 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
395 <td class="code ">
395 <td class="code ">
396 <pre><span class="tab-escape"> </span><del><span< del=""> <del>class=</del><del>"tab-escape"</del><del>&gt; </del>padding: <del>0</del>;
396 <pre><span class="tab-escape"> </span><del><span< del=""> <del>class=</del><del>"tab-escape"</del><del>&gt; </del>padding: <del>0</del>;
397 </span<></del></pre>
397 </span<></del></pre>
398 </td>
398 </td>
399 </tr>
399 </tr>
400 <tr class="line add">
400 <tr class="line add">
401 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o"></a></td>
401 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o"></a></td>
402 <td id="rhodecodepubliccssmainless_n2120" class="lineno new"><a href="#rhodecodepubliccssmainless_n2120">2120</a></td>
402 <td id="rhodecodepubliccssmainless_n2120" class="lineno new"><a href="#rhodecodepubliccssmainless_n2120">2120</a></td>
403 <td class="code ">
403 <td class="code ">
404 <pre><span class="tab-escape"> </span><ins> </ins> <ins> </ins><ins> </ins>padding: <ins>.9em</ins>;
404 <pre><span class="tab-escape"> </span><ins> </ins> <ins> </ins><ins> </ins>padding: <ins>.9em</ins>;
405 </pre>
405 </pre>
406 </td>
406 </td>
407 </tr>
407 </tr>
408 <tr class="line unmod">
408 <tr class="line unmod">
409 <td id="rhodecodepubliccssmainless_o2122" class="lineno old"><a href="#rhodecodepubliccssmainless_o2122">2122</a></td>
409 <td id="rhodecodepubliccssmainless_o2122" class="lineno old"><a href="#rhodecodepubliccssmainless_o2122">2122</a></td>
410 <td id="rhodecodepubliccssmainless_n2121" class="lineno new"><a href="#rhodecodepubliccssmainless_n2121">2121</a></td>
410 <td id="rhodecodepubliccssmainless_n2121" class="lineno new"><a href="#rhodecodepubliccssmainless_n2121">2121</a></td>
411 <td class="code ">
411 <td class="code ">
412 <pre></pre>
412 <pre></pre>
413 </td>
413 </td>
414 </tr>
414 </tr>
415 <tr class="line unmod">
415 <tr class="line unmod">
416 <td id="rhodecodepubliccssmainless_o2123" class="lineno old"><a href="#rhodecodepubliccssmainless_o2123">2123</a></td>
416 <td id="rhodecodepubliccssmainless_o2123" class="lineno old"><a href="#rhodecodepubliccssmainless_o2123">2123</a></td>
417 <td id="rhodecodepubliccssmainless_n2122" class="lineno new"><a href="#rhodecodepubliccssmainless_n2122">2122</a></td>
417 <td id="rhodecodepubliccssmainless_n2122" class="lineno new"><a href="#rhodecodepubliccssmainless_n2122">2122</a></td>
418 <td class="code ">
418 <td class="code ">
419 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>&amp;:after {
419 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>&amp;:after {
420 </pre>
420 </pre>
421 </td>
421 </td>
422 </tr>
422 </tr>
423 <tr class="line unmod">
423 <tr class="line unmod">
424 <td id="rhodecodepubliccssmainless_o2124" class="lineno old"><a href="#rhodecodepubliccssmainless_o2124">2124</a></td>
424 <td id="rhodecodepubliccssmainless_o2124" class="lineno old"><a href="#rhodecodepubliccssmainless_o2124">2124</a></td>
425 <td id="rhodecodepubliccssmainless_n2123" class="lineno new"><a href="#rhodecodepubliccssmainless_n2123">2123</a></td>
425 <td id="rhodecodepubliccssmainless_n2123" class="lineno new"><a href="#rhodecodepubliccssmainless_n2123">2123</a></td>
426 <td class="code ">
426 <td class="code ">
427 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span><span class="tab-escape"> </span>content: "\00A0\25BE";
427 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span><span class="tab-escape"> </span>content: "\00A0\25BE";
428 </pre>
428 </pre>
429 </td>
429 </td>
430 </tr>
430 </tr>
431 </tbody></table>
431 </tbody></table>
432 </div>
432 </div>
433 </div>
433 </div>
434 </div>
434 </div>
435
435
436 </td>
436 </td>
437 </tr>
437 </tr>
438 </tbody></table>
438 </tbody></table>
439 </div>
439 </div>
440
440
441
441
442
442
443
443
444
444
445
445
446
446
447
447
448
448
449 <!--
449 <!--
450 File View
450 File View
451 -->
451 -->
452
452
453 ##TODO: lisa: I believe this needs to be updated as the layout has changed.
453 ##TODO: lisa: I believe this needs to be updated as the layout has changed.
454 <h2>File View</h2>
454 <h2>File View</h2>
455
455
456 <div class="codeblock">
456 <div class="codeblock">
457 <div class="code-header">
457 <div class="code-header">
458 <div class="stats">
458 <div class="stats">
459 <div class="img">
459 <div class="img">
460 <i class="icon-file"></i>
460 <i class="icon-file"></i>
461 <span class="revision_id item"><a href="/example/changeset/fc252256eb0fcb4f2613e66f0126ea27967ae28c">r5487:fc252256eb0f</a></span>
461 <span class="revision_id item"><a href="/example/changeset/fc252256eb0fcb4f2613e66f0126ea27967ae28c">r5487:fc252256eb0f</a></span>
462 <span>1.2 KiB</span>
462 <span>1.2 KiB</span>
463 <span class="item last">text/x-python</span>
463 <span class="item last">text/x-python</span>
464 <div class="buttons">
464 <div class="buttons">
465
465
466 <a id="file_history_overview" class="btn btn-mini" href="#">
466 <a id="file_history_overview" class="btn btn-mini" href="#">
467 <i class="icon-time"></i> history
467 <i class="icon-time"></i> history
468 </a>
468 </a>
469 <a id="file_history_overview_full" class="btn btn-mini" style="display: none" href="/example/changelog/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
469 <a id="file_history_overview_full" class="btn btn-mini" style="display: none" href="/example/changelog/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
470 <i class="icon-time"></i> show full history
470 <i class="icon-time"></i> show full history
471 </a>
471 </a>
472 <a class="btn btn-mini" href="/example/annotate/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">annotation</a>
472 <a class="btn btn-mini" href="/example/annotate/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">annotation</a>
473 <a class="btn btn-mini" href="/example/raw/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">raw</a>
473 <a class="btn btn-mini" href="/example/raw/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">raw</a>
474 <a class="btn btn-mini" href="/example/rawfile/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
474 <a class="btn btn-mini" href="/example/rawfile/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
475 <i class="icon-archive"></i> download
475 <i class="icon-archive"></i> download
476 </a>
476 </a>
477
477
478 <a class="btn btn-mini disabled tooltip" href="#" title="Editing files allowed only when on branch head commit">edit</a>
478 <a class="btn btn-mini disabled tooltip" href="#" title="Editing files allowed only when on branch head commit">edit</a>
479 <a class="btn btn-mini btn-danger disabled tooltip" href="#" title="Deleting files allowed only when on branch head commit">delete</a>
479 <a class="btn btn-mini btn-danger disabled tooltip" href="#" title="Deleting files allowed only when on branch head commit">delete</a>
480 </div>
480 </div>
481 </div>
481 </div>
482 </div>
482 </div>
483 <div id="file_history_container"></div>
483 <div id="file_history_container"></div>
484 <div class="author">
484 <div class="author">
485 <div class="gravatar">
485 <div class="gravatar">
486 <img alt="gravatar" src="https://secure.gravatar.com/avatar/99e27b99c64003ca8c9875c9e3843495?d=identicon&amp;s=32" height="16" width="16">
486 <img alt="gravatar" src="https://secure.gravatar.com/avatar/99e27b99c64003ca8c9875c9e3843495?d=identicon&amp;s=32" height="16" width="16">
487 </div>
487 </div>
488 <div title="Marcin Kuzminski <marcin@python-works.com>" class="user">Marcin Kuzminski - <span class="tooltip" title="Wed, 02 Jul 2014 08:48:15">6m and 12d ago</span></div>
488 <div title="Marcin Kuzminski <marcin@python-works.com>" class="user">Marcin Kuzminski - <span class="tooltip" title="Wed, 02 Jul 2014 08:48:15">6m and 12d ago</span></div>
489 </div>
489 </div>
490 <div id="trimmed_message_box" class="commit">License changes</div>
490 <div id="trimmed_message_box" class="commit">License changes</div>
491 <div id="message_expand" style="display: none;">
491 <div id="message_expand" style="display: none;">
492 <i class="icon-resize-vertical"></i>
492 <i class="icon-resize-vertical"></i>
493 expand
493 expand
494 <i class="icon-resize-vertical"></i>
494 <i class="icon-resize-vertical"></i>
495 </div>
495 </div>
496 </div>
496 </div>
497 <div class="code-body">
497 <div class="code-body">
498 <table class="code-highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre><a href="#L1"> 1</a>
498 <table class="code-highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre><a href="#L1"> 1</a>
499 <a href="#L2"> 2</a>
499 <a href="#L2"> 2</a>
500 <a href="#L3"> 3</a>
500 <a href="#L3"> 3</a>
501 <a href="#L4"> 4</a>
501 <a href="#L4"> 4</a>
502 <a href="#L5"> 5</a>
502 <a href="#L5"> 5</a>
503 <a href="#L6"> 6</a>
503 <a href="#L6"> 6</a>
504 <a href="#L7"> 7</a>
504 <a href="#L7"> 7</a>
505 <a href="#L8"> 8</a>
505 <a href="#L8"> 8</a>
506 <a href="#L9"> 9</a>
506 <a href="#L9"> 9</a>
507 <a href="#L10">10</a>
507 <a href="#L10">10</a>
508 <a href="#L11">11</a>
508 <a href="#L11">11</a>
509 <a href="#L12">12</a>
509 <a href="#L12">12</a>
510 <a href="#L13">13</a>
510 <a href="#L13">13</a>
511 <a href="#L14">14</a>
511 <a href="#L14">14</a>
512 <a href="#L15">15</a>
512 <a href="#L15">15</a>
513 <a href="#L16">16</a>
513 <a href="#L16">16</a>
514 <a href="#L17">17</a>
514 <a href="#L17">17</a>
515 <a href="#L18">18</a>
515 <a href="#L18">18</a>
516 <a href="#L19">19</a>
516 <a href="#L19">19</a>
517 <a href="#L20">20</a>
517 <a href="#L20">20</a>
518 <a href="#L21">21</a>
518 <a href="#L21">21</a>
519 <a href="#L22">22</a>
519 <a href="#L22">22</a>
520 <a href="#L23">23</a>
520 <a href="#L23">23</a>
521 <a href="#L24">24</a>
521 <a href="#L24">24</a>
522 <a href="#L25">25</a>
522 <a href="#L25">25</a>
523 <a href="#L26">26</a>
523 <a href="#L26">26</a>
524 <a href="#L27">27</a>
524 <a href="#L27">27</a>
525 <a href="#L28">28</a>
525 <a href="#L28">28</a>
526 <a href="#L29">29</a>
526 <a href="#L29">29</a>
527 <a href="#L30">30</a>
527 <a href="#L30">30</a>
528 <a href="#L31">31</a>
528 <a href="#L31">31</a>
529 <a href="#L32">32</a>
529 <a href="#L32">32</a>
530 <a href="#L33">33</a>
530 <a href="#L33">33</a>
531 <a href="#L34">34</a>
531 <a href="#L34">34</a>
532 <a href="#L35">35</a>
532 <a href="#L35">35</a>
533 <a href="#L36">36</a>
533 <a href="#L36">36</a>
534 <a href="#L37">37</a>
534 <a href="#L37">37</a>
535 <a href="#L38">38</a>
535 <a href="#L38">38</a>
536 <a href="#L39">39</a>
536 <a href="#L39">39</a>
537 <a href="#L40">40</a>
537 <a href="#L40">40</a>
538 <a href="#L41">41</a>
538 <a href="#L41">41</a>
539 <a href="#L42">42</a></pre></div></td><td id="hlcode" class="code"><div class="code-highlight"><pre><div id="L1"><a name="L-1"></a><span class="c"># -*- coding: utf-8 -*-</span>
539 <a href="#L42">42</a></pre></div></td><td id="hlcode" class="code"><div class="code-highlight"><pre><div id="L1"><a name="L-1"></a><span class="c"># -*- coding: utf-8 -*-</span>
540 </div><div id="L2"><a name="L-2"></a>
540 </div><div id="L2"><a name="L-2"></a>
541 </div><div id="L3"><a name="L-3"></a><span class="c"># Published under Business Source License.</span>
541 </div><div id="L3"><a name="L-3"></a><span class="c"># Published under Business Source License.</span>
542 </div><div id="L4"><a name="L-4"></a><span class="c"># Read the full license text at https://rhodecode.com/licenses.</span>
542 </div><div id="L4"><a name="L-4"></a><span class="c"># Read the full license text at https://rhodecode.com/licenses.</span>
543 </div><div id="L5"><a name="L-5"></a><span class="sd">"""</span>
543 </div><div id="L5"><a name="L-5"></a><span class="sd">"""</span>
544 </div><div id="L6"><a name="L-6"></a><span class="sd">rhodecode.websetup</span>
544 </div><div id="L6"><a name="L-6"></a><span class="sd">rhodecode.websetup</span>
545 </div><div id="L7"><a name="L-7"></a><span class="sd">~~~~~~~~~~~~~~~~~~</span>
545 </div><div id="L7"><a name="L-7"></a><span class="sd">~~~~~~~~~~~~~~~~~~</span>
546 </div><div id="L8"><a name="L-8"></a>
546 </div><div id="L8"><a name="L-8"></a>
547 </div><div id="L9"><a name="L-9"></a><span class="sd">Weboperations and setup for rhodecode. Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</span>
547 </div><div id="L9"><a name="L-9"></a><span class="sd">Weboperations and setup for rhodecode. Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</span>
548 </div><div id="L10"><a name="L-10"></a>
548 </div><div id="L10"><a name="L-10"></a>
549 </div><div id="L11"><a name="L-11"></a><span class="sd">:created_on: Dec 11, 2010</span>
549 </div><div id="L11"><a name="L-11"></a><span class="sd">:created_on: Dec 11, 2010</span>
550 </div><div id="L12"><a name="L-12"></a><span class="sd">:author: marcink</span>
550 </div><div id="L12"><a name="L-12"></a><span class="sd">:author: marcink</span>
551 </div><div id="L13"><a name="L-13"></a><span class="sd">:copyright: (c) 2013-2015 RhodeCode GmbH.</span>
551 </div><div id="L13"><a name="L-13"></a><span class="sd">:copyright: (c) 2013-2015 RhodeCode GmbH.</span>
552 </div><div id="L14"><a name="L-14"></a><span class="sd">:license: Business Source License, see LICENSE for more details.</span>
552 </div><div id="L14"><a name="L-14"></a><span class="sd">:license: Business Source License, see LICENSE for more details.</span>
553 </div><div id="L15"><a name="L-15"></a><span class="sd">"""</span>
553 </div><div id="L15"><a name="L-15"></a><span class="sd">"""</span>
554 </div><div id="L16"><a name="L-16"></a>
554 </div><div id="L16"><a name="L-16"></a>
555 </div><div id="L17"><a name="L-17"></a><span class="kn">import</span> <span class="nn">logging</span>
555 </div><div id="L17"><a name="L-17"></a><span class="kn">import</span> <span class="nn">logging</span>
556 </div><div id="L18"><a name="L-18"></a>
556 </div><div id="L18"><a name="L-18"></a>
557 </div><div id="L19"><a name="L-19"></a><span class="kn">from</span> <span class="nn">rhodecode.config.environment</span> <span class="kn">import</span> <span class="n">load_environment</span>
557 </div><div id="L19"><a name="L-19"></a><span class="kn">from</span> <span class="nn">rhodecode.config.environment</span> <span class="kn">import</span> <span class="n">load_environment</span>
558 </div><div id="L20"><a name="L-20"></a><span class="kn">from</span> <span class="nn">rhodecode.lib.db_manage</span> <span class="kn">import</span> <span class="n">DbManage</span>
558 </div><div id="L20"><a name="L-20"></a><span class="kn">from</span> <span class="nn">rhodecode.lib.db_manage</span> <span class="kn">import</span> <span class="n">DbManage</span>
559 </div><div id="L21"><a name="L-21"></a><span class="kn">from</span> <span class="nn">rhodecode.model.meta</span> <span class="kn">import</span> <span class="n">Session</span>
559 </div><div id="L21"><a name="L-21"></a><span class="kn">from</span> <span class="nn">rhodecode.model.meta</span> <span class="kn">import</span> <span class="n">Session</span>
560 </div><div id="L22"><a name="L-22"></a>
560 </div><div id="L22"><a name="L-22"></a>
561 </div><div id="L23"><a name="L-23"></a>
561 </div><div id="L23"><a name="L-23"></a>
562 </div><div id="L24"><a name="L-24"></a><span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
562 </div><div id="L24"><a name="L-24"></a><span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
563 </div><div id="L25"><a name="L-25"></a>
563 </div><div id="L25"><a name="L-25"></a>
564 </div><div id="L26"><a name="L-26"></a>
564 </div><div id="L26"><a name="L-26"></a>
565 </div><div id="L27"><a name="L-27"></a><span class="k">def</span> <span class="nf">setup_app</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">conf</span><span class="p">,</span> <span class="nb">vars</span><span class="p">):</span>
565 </div><div id="L27"><a name="L-27"></a><span class="k">def</span> <span class="nf">setup_app</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">conf</span><span class="p">,</span> <span class="nb">vars</span><span class="p">):</span>
566 </div><div id="L28"><a name="L-28"></a> <span class="sd">"""Place any commands to setup rhodecode here"""</span>
566 </div><div id="L28"><a name="L-28"></a> <span class="sd">"""Place any commands to setup rhodecode here"""</span>
567 </div><div id="L29"><a name="L-29"></a> <span class="n">dbconf</span> <span class="o">=</span> <span class="n">conf</span><span class="p">[</span><span class="s">'sqlalchemy.db1.url'</span><span class="p">]</span>
567 </div><div id="L29"><a name="L-29"></a> <span class="n">dbconf</span> <span class="o">=</span> <span class="n">conf</span><span class="p">[</span><span class="s">'sqlalchemy.db1.url'</span><span class="p">]</span>
568 </div><div id="L30"><a name="L-30"></a> <span class="n">dbmanage</span> <span class="o">=</span> <span class="n">DbManage</span><span class="p">(</span><span class="n">log_sql</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">dbconf</span><span class="o">=</span><span class="n">dbconf</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="n">conf</span><span class="p">[</span><span class="s">'here'</span><span class="p">],</span>
568 </div><div id="L30"><a name="L-30"></a> <span class="n">dbmanage</span> <span class="o">=</span> <span class="n">DbManage</span><span class="p">(</span><span class="n">log_sql</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">dbconf</span><span class="o">=</span><span class="n">dbconf</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="n">conf</span><span class="p">[</span><span class="s">'here'</span><span class="p">],</span>
569 </div><div id="L31"><a name="L-31"></a> <span class="n">tests</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">cli_args</span><span class="o">=</span><span class="n">command</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">__dict__</span><span class="p">)</span>
569 </div><div id="L31"><a name="L-31"></a> <span class="n">tests</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">cli_args</span><span class="o">=</span><span class="n">command</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">__dict__</span><span class="p">)</span>
570 </div><div id="L32"><a name="L-32"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_tables</span><span class="p">(</span><span class="n">override</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
570 </div><div id="L32"><a name="L-32"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_tables</span><span class="p">(</span><span class="n">override</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
571 </div><div id="L33"><a name="L-33"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">set_db_version</span><span class="p">()</span>
571 </div><div id="L33"><a name="L-33"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">set_db_version</span><span class="p">()</span>
572 </div><div id="L34"><a name="L-34"></a> <span class="n">opts</span> <span class="o">=</span> <span class="n">dbmanage</span><span class="o">.</span><span class="n">config_prompt</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
572 </div><div id="L34"><a name="L-34"></a> <span class="n">opts</span> <span class="o">=</span> <span class="n">dbmanage</span><span class="o">.</span><span class="n">config_prompt</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
573 </div><div id="L35"><a name="L-35"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_settings</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
573 </div><div id="L35"><a name="L-35"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_settings</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
574 </div><div id="L36"><a name="L-36"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_default_user</span><span class="p">()</span>
574 </div><div id="L36"><a name="L-36"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_default_user</span><span class="p">()</span>
575 </div><div id="L37"><a name="L-37"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">admin_prompt</span><span class="p">()</span>
575 </div><div id="L37"><a name="L-37"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">admin_prompt</span><span class="p">()</span>
576 </div><div id="L38"><a name="L-38"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_permissions</span><span class="p">()</span>
576 </div><div id="L38"><a name="L-38"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_permissions</span><span class="p">()</span>
577 </div><div id="L39"><a name="L-39"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">populate_default_permissions</span><span class="p">()</span>
577 </div><div id="L39"><a name="L-39"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">populate_default_permissions</span><span class="p">()</span>
578 </div><div id="L40"><a name="L-40"></a> <span class="n">Session</span><span class="p">()</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
578 </div><div id="L40"><a name="L-40"></a> <span class="n">Session</span><span class="p">()</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
579 </div><div id="L41"><a name="L-41"></a> <span class="n">load_environment</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">global_conf</span><span class="p">,</span> <span class="n">conf</span><span class="o">.</span><span class="n">local_conf</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
579 </div><div id="L41"><a name="L-41"></a> <span class="n">load_environment</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">global_conf</span><span class="p">,</span> <span class="n">conf</span><span class="o">.</span><span class="n">local_conf</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
580 </div><div id="L42"><a name="L-42"></a> <span class="n">DbManage</span><span class="o">.</span><span class="n">check_waitress</span><span class="p">()</span>
580 </div><div id="L42"><a name="L-42"></a> <span class="n">DbManage</span><span class="o">.</span><span class="n">check_waitress</span><span class="p">()</span>
581 </div></pre></div>
581 </div></pre></div>
582 </td></tr></tbody></table>
582 </td></tr></tbody></table>
583 </div>
583 </div>
584 </div>
584 </div>
585
585
586
586
587
587
588
588
589
589
590
590
591
591
592
592
593
593
594 <!--
594 <!--
595 Gist Edit
595 Gist Edit
596 -->
596 -->
597
597
598
598
599 <h2>Gist Edit</h2>
599 <h2>Gist Edit</h2>
600
600
601 <div class="codeblock">
601 <div class="codeblock">
602 <div class="code-header">
602 <div class="code-header">
603 <div class="form">
603 <div class="form">
604 <div class="fields">
604 <div class="fields">
605 <input id="filename" name="filename" placeholder="name this file..." size="30" type="text">
605 <input id="filename" name="filename" placeholder="name this file..." size="30" type="text">
606 <div class="select2-container drop-menu" id="s2id_mimetype"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">Python</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen"></label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen3_search" class="select2-offscreen"></label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="mimetype" name="mimetype" tabindex="-1" title="" style="display: none;">
606 <div class="select2-container drop-menu" id="s2id_mimetype"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">Python</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen"></label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen3_search" class="select2-offscreen"></label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="mimetype" name="mimetype" tabindex="-1" title="" style="display: none;">
607 <option selected="selected" value="plain">plain</option>
607 <option selected="selected" value="plain">plain</option>
608 <option value="text/apl" mode="apl">APL</option><option value="text/x-asterisk" mode="asterisk">Asterisk</option><option value="text/x-csrc" mode="clike">C</option><option value="text/x-c++src" mode="clike">C++</option><option value="text/x-cobol" mode="cobol">Cobol</option><option value="text/x-java" mode="clike">Java</option><option value="text/x-csharp" mode="clike">C#</option><option value="text/x-scala" mode="clike">Scala</option><option value="text/x-clojure" mode="clojure">Clojure</option><option value="text/x-coffeescript" mode="coffeescript">CoffeeScript</option><option value="text/x-common-lisp" mode="commonlisp">Common Lisp</option><option value="text/css" mode="css">CSS</option><option value="text/x-d" mode="d">D</option><option value="text/x-diff" mode="diff">diff</option><option value="application/xml-dtd" mode="dtd">DTD</option><option value="text/x-dylan" mode="dylan">Dylan</option><option value="text/x-ecl" mode="ecl">ECL</option><option value="text/x-eiffel" mode="eiffel">Eiffel</option><option value="text/x-erlang" mode="erlang">Erlang</option><option value="text/x-fortran" mode="fortran">Fortran</option><option value="text/x-fsharp" mode="mllike">F#</option><option value="text/x-gas" mode="gas">Gas</option><option value="text/x-go" mode="go">GO</option><option value="text/x-feature" mode="gherkin">Gherkin</option><option value="text/x-go" mode="go">Go</option><option value="text/x-groovy" mode="groovy">Groovy</option><option value="text/x-haml" mode="haml">HAML</option><option value="text/x-haskell" mode="haskell">Haskell</option><option value="text/x-haxe" mode="haxe">Haxe</option><option value="application/x-aspx" mode="htmlembedded">ASP.NET</option><option value="application/x-ejs" mode="htmlembedded">Embedded Javascript</option><option value="application/x-jsp" mode="htmlembedded">JavaServer Pages</option><option value="text/html" mode="htmlmixed">HTML</option><option value="message/http" mode="http">HTTP</option><option value="text/x-jade" mode="jade">Jade</option><option value="text/javascript" mode="javascript">JavaScript</option><option value="application/json" mode="javascript">JSON</option><option value="application/typescript" mode="javascript">TypeScript</option><option value="jinja2" mode="jinja2">Jinja2</option><option value="text/x-julia" mode="julia">Julia</option><option value="text/x-less" mode="less">LESS</option><option value="text/x-livescript" mode="livescript">LiveScript</option><option value="text/x-lua" mode="lua">Lua</option><option value="text/x-markdown" mode="markdown">Markdown (GitHub-flavour)</option><option value="text/mirc" mode="mirc">mIRC</option><option value="text/x-nginx-conf" mode="nginx">Nginx</option><option value="text/n-triples" mode="ntriples">NTriples</option><option value="text/x-ocaml" mode="ocaml">OCaml</option><option value="text/x-ocaml" mode="mllike">OCaml</option><option value="text/x-octave" mode="octave">Octave</option><option value="text/x-pascal" mode="pascal">Pascal</option><option value="null" mode="pegjs">PEG.js</option><option value="text/x-perl" mode="perl">Perl</option><option value="text/x-php" mode="php">PHP</option><option value="text/x-pig" mode="pig">Pig</option><option value="text/plain" mode="null">Plain Text</option><option value="text/x-properties" mode="properties">Properties files</option><option value="text/x-python" mode="python">Python</option><option value="text/x-puppet" mode="puppet">Puppet</option><option value="text/x-rsrc" mode="r">R</option><option value="text/x-rst" mode="rst">reStructuredText</option><option value="text/x-ruby" mode="ruby">Ruby</option><option value="text/x-rustsrc" mode="rust">Rust</option><option value="text/x-sass" mode="sass">Sass</option><option value="text/x-scheme" mode="scheme">Scheme</option><option value="text/x-scss" mode="css">SCSS</option><option value="text/x-sh" mode="shell">Shell</option><option value="application/sieve" mode="sieve">Sieve</option><option value="text/x-stsrc" mode="smalltalk">Smalltalk</option><option value="text/x-smarty" mode="smarty">Smarty</option><option value="text/x-smarty" mode="smartymixed">SmartyMixed</option><option value="text/x-solr" mode="solr">Solr</option><option value="application/x-sparql-query" mode="sparql">SPARQL</option><option value="text/x-sql" mode="sql">SQL</option><option value="text/x-mariadb" mode="sql">MariaDB</option><option value="text/x-stex" mode="stex">sTeX</option><option value="text/x-latex" mode="stex">LaTeX</option><option value="text/x-systemverilog" mode="verilog">SystemVerilog</option><option value="text/x-tcl" mode="tcl">Tcl</option><option value="text/x-tiddlywiki" mode="tiddlywiki">TiddlyWiki </option><option value="text/tiki" mode="tiki">Tiki wiki</option><option value="text/x-toml" mode="toml">TOML</option><option value="text/turtle" mode="turtle">Turtle</option><option value="text/x-vb" mode="vb">VB.NET</option><option value="text/vbscript" mode="vbscript">VBScript</option><option value="text/velocity" mode="velocity">Velocity</option><option value="text/x-verilog" mode="verilog">Verilog</option><option value="application/xml" mode="xml">XML</option><option value="text/html" mode="xml">HTML</option><option value="application/xquery" mode="xquery">XQuery</option><option value="text/x-yaml" mode="yaml">YAML</option><option value="text/x-z80" mode="z80">Z80</option></select>
608 <option value="text/apl" mode="apl">APL</option><option value="text/x-asterisk" mode="asterisk">Asterisk</option><option value="text/x-csrc" mode="clike">C</option><option value="text/x-c++src" mode="clike">C++</option><option value="text/x-cobol" mode="cobol">Cobol</option><option value="text/x-java" mode="clike">Java</option><option value="text/x-csharp" mode="clike">C#</option><option value="text/x-scala" mode="clike">Scala</option><option value="text/x-clojure" mode="clojure">Clojure</option><option value="text/x-coffeescript" mode="coffeescript">CoffeeScript</option><option value="text/x-common-lisp" mode="commonlisp">Common Lisp</option><option value="text/css" mode="css">CSS</option><option value="text/x-d" mode="d">D</option><option value="text/x-diff" mode="diff">diff</option><option value="application/xml-dtd" mode="dtd">DTD</option><option value="text/x-dylan" mode="dylan">Dylan</option><option value="text/x-ecl" mode="ecl">ECL</option><option value="text/x-eiffel" mode="eiffel">Eiffel</option><option value="text/x-erlang" mode="erlang">Erlang</option><option value="text/x-fortran" mode="fortran">Fortran</option><option value="text/x-fsharp" mode="mllike">F#</option><option value="text/x-gas" mode="gas">Gas</option><option value="text/x-go" mode="go">GO</option><option value="text/x-feature" mode="gherkin">Gherkin</option><option value="text/x-go" mode="go">Go</option><option value="text/x-groovy" mode="groovy">Groovy</option><option value="text/x-haml" mode="haml">HAML</option><option value="text/x-haskell" mode="haskell">Haskell</option><option value="text/x-haxe" mode="haxe">Haxe</option><option value="application/x-aspx" mode="htmlembedded">ASP.NET</option><option value="application/x-ejs" mode="htmlembedded">Embedded Javascript</option><option value="application/x-jsp" mode="htmlembedded">JavaServer Pages</option><option value="text/html" mode="htmlmixed">HTML</option><option value="message/http" mode="http">HTTP</option><option value="text/x-jade" mode="jade">Jade</option><option value="text/javascript" mode="javascript">JavaScript</option><option value="application/json" mode="javascript">JSON</option><option value="application/typescript" mode="javascript">TypeScript</option><option value="jinja2" mode="jinja2">Jinja2</option><option value="text/x-julia" mode="julia">Julia</option><option value="text/x-less" mode="less">LESS</option><option value="text/x-livescript" mode="livescript">LiveScript</option><option value="text/x-lua" mode="lua">Lua</option><option value="text/x-markdown" mode="markdown">Markdown (GitHub-flavour)</option><option value="text/mirc" mode="mirc">mIRC</option><option value="text/x-nginx-conf" mode="nginx">Nginx</option><option value="text/n-triples" mode="ntriples">NTriples</option><option value="text/x-ocaml" mode="ocaml">OCaml</option><option value="text/x-ocaml" mode="mllike">OCaml</option><option value="text/x-octave" mode="octave">Octave</option><option value="text/x-pascal" mode="pascal">Pascal</option><option value="null" mode="pegjs">PEG.js</option><option value="text/x-perl" mode="perl">Perl</option><option value="text/x-php" mode="php">PHP</option><option value="text/x-pig" mode="pig">Pig</option><option value="text/plain" mode="null">Plain Text</option><option value="text/x-properties" mode="properties">Properties files</option><option value="text/x-python" mode="python">Python</option><option value="text/x-puppet" mode="puppet">Puppet</option><option value="text/x-rsrc" mode="r">R</option><option value="text/x-rst" mode="rst">reStructuredText</option><option value="text/x-ruby" mode="ruby">Ruby</option><option value="text/x-rustsrc" mode="rust">Rust</option><option value="text/x-sass" mode="sass">Sass</option><option value="text/x-scheme" mode="scheme">Scheme</option><option value="text/x-scss" mode="css">SCSS</option><option value="text/x-sh" mode="shell">Shell</option><option value="application/sieve" mode="sieve">Sieve</option><option value="text/x-stsrc" mode="smalltalk">Smalltalk</option><option value="text/x-smarty" mode="smarty">Smarty</option><option value="text/x-smarty" mode="smartymixed">SmartyMixed</option><option value="text/x-solr" mode="solr">Solr</option><option value="application/x-sparql-query" mode="sparql">SPARQL</option><option value="text/x-sql" mode="sql">SQL</option><option value="text/x-mariadb" mode="sql">MariaDB</option><option value="text/x-stex" mode="stex">sTeX</option><option value="text/x-latex" mode="stex">LaTeX</option><option value="text/x-systemverilog" mode="verilog">SystemVerilog</option><option value="text/x-tcl" mode="tcl">Tcl</option><option value="text/x-tiddlywiki" mode="tiddlywiki">TiddlyWiki </option><option value="text/tiki" mode="tiki">Tiki wiki</option><option value="text/x-toml" mode="toml">TOML</option><option value="text/turtle" mode="turtle">Turtle</option><option value="text/x-vb" mode="vb">VB.NET</option><option value="text/vbscript" mode="vbscript">VBScript</option><option value="text/velocity" mode="velocity">Velocity</option><option value="text/x-verilog" mode="verilog">Verilog</option><option value="application/xml" mode="xml">XML</option><option value="text/html" mode="xml">HTML</option><option value="application/xquery" mode="xquery">XQuery</option><option value="text/x-yaml" mode="yaml">YAML</option><option value="text/x-z80" mode="z80">Z80</option></select>
609 <script>
609 <script>
610 $(document).ready(function() {
610 $(document).ready(function() {
611 $('#mimetype').select2({
611 $('#mimetype').select2({
612 containerCssClass: 'drop-menu',
612 containerCssClass: 'drop-menu',
613 dropdownCssClass: 'drop-menu-dropdown',
613 dropdownCssClass: 'drop-menu-dropdown',
614 dropdownAutoWidth: true
614 dropdownAutoWidth: true
615 });
615 });
616 });
616 });
617 </script>
617 </script>
618
618
619 </div>
619 </div>
620 </div>
620 </div>
621 </div>
621 </div>
622 <div id="editor_container">
622 <div id="editor_container">
623 <div id="editor_pre"></div>
623 <div id="editor_pre"></div>
624 <textarea id="editor" name="content" style="display: none;"></textarea><div class="CodeMirror cm-s-default"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 484px; left: 219.4091796875px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="min-width: 18px; display: block; bottom: 0px;"><div style="min-width: 1px; height: 619px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 700.269653320313px; margin-left: 29px; min-height: 619px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div class="CodeMirror-linenumber CodeMirror-gutter-elt"><div>47</div></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">re</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">text</span> <span class="cm-keyword">import</span> <span class="cm-variable">compress_sequence</span>, <span class="cm-variable">compress_string</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">cache</span> <span class="cm-keyword">import</span> <span class="cm-variable">patch_vary_headers</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-variable">re_accepts_gzip</span> = <span class="cm-variable">re</span>.<span class="cm-builtin">compile</span>(<span class="cm-string">r'\bgzip\b'</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-keyword">class</span> <span class="cm-def">GZipMiddleware</span>(<span class="cm-builtin">object</span>): # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre> <span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string"> This middleware compresses content if the browser allows gzip compression.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string"> It sets the Vary header accordingly, so that caches will base their storage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string"> on the Accept-Encoding header.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string"> """</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre> <span class="cm-keyword">def</span> <span class="cm-def">process_response</span>(<span class="cm-variable-2">self</span>, <span class="cm-variable">request</span>, <span class="cm-variable">response</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre> <span class="cm-comment"># It's not worth attempting to compress really short responses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span> <span class="cm-operator">and</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>) <span class="cm-operator">&lt;</span> <span class="cm-number">200</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre> <span class="cm-comment"># Avoid gzipping if we've already got a content-encoding.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'Content-Encoding'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre> <span class="cm-variable">patch_vary_headers</span>(<span class="cm-variable">response</span>, (<span class="cm-string">'Accept-Encoding'</span>,))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre> <span class="cm-variable">ae</span> = <span class="cm-variable">request</span>.<span class="cm-variable">META</span>.<span class="cm-variable">get</span>(<span class="cm-string">'HTTP_ACCEPT_ENCODING'</span>, <span class="cm-string">''</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">re_accepts_gzip</span>.<span class="cm-variable">search</span>(<span class="cm-variable">ae</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-comment"># Delete the `Content-Length` header for streaming content, because</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-comment"># we won't know the compressed size until we stream it.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span> = <span class="cm-variable">compress_sequence</span>(<span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-keyword">del</span> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-keyword">else</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-comment"># Return the compressed content only if it's actually shorter.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">compressed_content</span> = <span class="cm-variable">compress_string</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-builtin">len</span>(<span class="cm-variable">compressed_content</span>) <span class="cm-operator">&gt;=</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">content</span> = <span class="cm-variable">compressed_content</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>] = <span class="cm-builtin">str</span>(<span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">43</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'ETag'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">44</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>] = <span class="cm-variable">re</span>.<span class="cm-variable">sub</span>(<span class="cm-string">'"$'</span>, <span class="cm-string">';gzip"'</span>, <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>])</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">45</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Encoding'</span>] = <span class="cm-string">'gzip'</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">46</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">47</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div></div><div class="CodeMirror-cursor" style="left: 189.4091796875px; top: 598px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 619px;"></div><div class="CodeMirror-gutters" style="height: 619px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
624 <textarea id="editor" name="content" style="display: none;"></textarea><div class="CodeMirror cm-s-default"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 484px; left: 219.4091796875px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="min-width: 18px; display: block; bottom: 0px;"><div style="min-width: 1px; height: 619px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 700.269653320313px; margin-left: 29px; min-height: 619px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div class="CodeMirror-linenumber CodeMirror-gutter-elt"><div>47</div></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">re</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">text</span> <span class="cm-keyword">import</span> <span class="cm-variable">compress_sequence</span>, <span class="cm-variable">compress_string</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">cache</span> <span class="cm-keyword">import</span> <span class="cm-variable">patch_vary_headers</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-variable">re_accepts_gzip</span> = <span class="cm-variable">re</span>.<span class="cm-builtin">compile</span>(<span class="cm-string">r'\bgzip\b'</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-keyword">class</span> <span class="cm-def">GZipMiddleware</span>(<span class="cm-builtin">object</span>): # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre> <span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string"> This middleware compresses content if the browser allows gzip compression.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string"> It sets the Vary header accordingly, so that caches will base their storage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string"> on the Accept-Encoding header.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string"> """</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre> <span class="cm-keyword">def</span> <span class="cm-def">process_response</span>(<span class="cm-variable-2">self</span>, <span class="cm-variable">request</span>, <span class="cm-variable">response</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre> <span class="cm-comment"># It's not worth attempting to compress really short responses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span> <span class="cm-operator">and</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>) <span class="cm-operator">&lt;</span> <span class="cm-number">200</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre> <span class="cm-comment"># Avoid gzipping if we've already got a content-encoding.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'Content-Encoding'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre> <span class="cm-variable">patch_vary_headers</span>(<span class="cm-variable">response</span>, (<span class="cm-string">'Accept-Encoding'</span>,))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre> <span class="cm-variable">ae</span> = <span class="cm-variable">request</span>.<span class="cm-variable">META</span>.<span class="cm-variable">get</span>(<span class="cm-string">'HTTP_ACCEPT_ENCODING'</span>, <span class="cm-string">''</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">re_accepts_gzip</span>.<span class="cm-variable">search</span>(<span class="cm-variable">ae</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-comment"># Delete the `Content-Length` header for streaming content, because</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-comment"># we won't know the compressed size until we stream it.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span> = <span class="cm-variable">compress_sequence</span>(<span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-keyword">del</span> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-keyword">else</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-comment"># Return the compressed content only if it's actually shorter.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">compressed_content</span> = <span class="cm-variable">compress_string</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-builtin">len</span>(<span class="cm-variable">compressed_content</span>) <span class="cm-operator">&gt;=</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">content</span> = <span class="cm-variable">compressed_content</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>] = <span class="cm-builtin">str</span>(<span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">43</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'ETag'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">44</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>] = <span class="cm-variable">re</span>.<span class="cm-variable">sub</span>(<span class="cm-string">'"$'</span>, <span class="cm-string">';gzip"'</span>, <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>])</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">45</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Encoding'</span>] = <span class="cm-string">'gzip'</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">46</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">47</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div></div><div class="CodeMirror-cursor" style="left: 189.4091796875px; top: 598px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 619px;"></div><div class="CodeMirror-gutters" style="height: 619px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
625 </div>
625 </div>
626 </div>
626 </div>
627
627
628
628
629
629
630
630
631
631
632 <!--
632 <!--
633 File Edit
633 File Edit
634 -->
634 -->
635
635
636 <h2>File Edit</h2>
636 <h2>File Edit</h2>
637
637
638 <div class="codeblock">
638 <div class="codeblock">
639 <div class="code-header">
639 <div class="code-header">
640 <div class="stats">
640 <div class="stats">
641 <i class="icon-file"></i>
641 <i class="icon-file"></i>
642 <span class="item"><a href="/example/changeset/80ead1899f50a894889e19ffeb49c9cebf5bf045">r8248:80ead1899f50</a></span>
642 <span class="item"><a href="/example/changeset/80ead1899f50a894889e19ffeb49c9cebf5bf045">r8248:80ead1899f50</a></span>
643 <span class="item">1.2 KiB</span>
643 <span class="item">1.2 KiB</span>
644 <span class="item last">text/x-python</span>
644 <span class="item last">text/x-python</span>
645 <div class="buttons">
645 <div class="buttons">
646 <a class="btn btn-mini" href="/example/changelog/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
646 <a class="btn btn-mini" href="/example/changelog/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
647 <i class="icon-time"></i> history
647 <i class="icon-time"></i> history
648 </a>
648 </a>
649
649
650 <a class="btn btn-mini" href="/example/files/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">source</a>
650 <a class="btn btn-mini" href="/example/files/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">source</a>
651 <a class="btn btn-mini" href="/example/raw/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">raw</a>
651 <a class="btn btn-mini" href="/example/raw/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">raw</a>
652 <a class="btn btn-mini" href="/example/rawfile/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
652 <a class="btn btn-mini" href="/example/rawfile/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
653 <i class="icon-archive"></i> download
653 <i class="icon-archive"></i> download
654 </a>
654 </a>
655 </div>
655 </div>
656 </div>
656 </div>
657 <div class="form">
657 <div class="form">
658 <label for="set_mode">Editing file:</label>
658 <label for="set_mode">Editing file:</label>
659 rhodecode /
659 rhodecode /
660 <input type="text" name="filename" value="websetup.py">
660 <input type="text" name="filename" value="websetup.py">
661
661
662 <div class="select2-container drop-menu" id="s2id_set_mode"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-2">plain</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen2" class="select2-offscreen">Editing file:</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-2" id="s2id_autogen2"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen2_search" class="select2-offscreen">Editing file:</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-2" id="s2id_autogen2_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-2"> </ul></div></div><select id="set_mode" name="set_mode" tabindex="-1" title="Editing file:" style="display: none;">
662 <div class="select2-container drop-menu" id="s2id_set_mode"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-2">plain</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen2" class="select2-offscreen">Editing file:</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-2" id="s2id_autogen2"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen2_search" class="select2-offscreen">Editing file:</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-2" id="s2id_autogen2_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-2"> </ul></div></div><select id="set_mode" name="set_mode" tabindex="-1" title="Editing file:" style="display: none;">
663 <option selected="selected" value="plain">plain</option>
663 <option selected="selected" value="plain">plain</option>
664 <option value="apl">APL</option><option value="asterisk">Asterisk</option><option value="clike">C</option><option value="clike">C++</option><option value="cobol">Cobol</option><option value="clike">Java</option><option value="clike">C#</option><option value="clike">Scala</option><option value="clojure">Clojure</option><option value="coffeescript">CoffeeScript</option><option value="commonlisp">Common Lisp</option><option value="css">CSS</option><option value="d">D</option><option value="diff">diff</option><option value="dtd">DTD</option><option value="dylan">Dylan</option><option value="ecl">ECL</option><option value="eiffel">Eiffel</option><option value="erlang">Erlang</option><option value="fortran">Fortran</option><option value="mllike">F#</option><option value="gas">Gas</option><option value="go">GO</option><option value="gherkin">Gherkin</option><option value="go">Go</option><option value="groovy">Groovy</option><option value="haml">HAML</option><option value="haskell">Haskell</option><option value="haxe">Haxe</option><option value="htmlembedded">ASP.NET</option><option value="htmlembedded">Embedded Javascript</option><option value="htmlembedded">JavaServer Pages</option><option value="htmlmixed">HTML</option><option value="http">HTTP</option><option value="jade">Jade</option><option value="javascript">JavaScript</option><option value="javascript">JSON</option><option value="javascript">TypeScript</option><option value="jinja2">Jinja2</option><option value="julia">Julia</option><option value="less">LESS</option><option value="livescript">LiveScript</option><option value="lua">Lua</option><option value="markdown">Markdown (GitHub-flavour)</option><option value="mirc">mIRC</option><option value="nginx">Nginx</option><option value="ntriples">NTriples</option><option value="ocaml">OCaml</option><option value="mllike">OCaml</option><option value="octave">Octave</option><option value="pascal">Pascal</option><option value="pegjs">PEG.js</option><option value="perl">Perl</option><option value="php">PHP</option><option value="pig">Pig</option><option value="null">Plain Text</option><option value="properties">Properties files</option><option value="python" selected="selected">Python</option><option value="puppet">Puppet</option><option value="r">R</option><option value="rst">reStructuredText</option><option value="ruby">Ruby</option><option value="rust">Rust</option><option value="sass">Sass</option><option value="scheme">Scheme</option><option value="css">SCSS</option><option value="shell">Shell</option><option value="sieve">Sieve</option><option value="smalltalk">Smalltalk</option><option value="smarty">Smarty</option><option value="smartymixed">SmartyMixed</option><option value="solr">Solr</option><option value="sparql">SPARQL</option><option value="sql">SQL</option><option value="sql">MariaDB</option><option value="stex">sTeX</option><option value="stex">LaTeX</option><option value="verilog">SystemVerilog</option><option value="tcl">Tcl</option><option value="tiddlywiki">TiddlyWiki </option><option value="tiki">Tiki wiki</option><option value="toml">TOML</option><option value="turtle">Turtle</option><option value="vb">VB.NET</option><option value="vbscript">VBScript</option><option value="velocity">Velocity</option><option value="verilog">Verilog</option><option value="xml">XML</option><option value="xml">HTML</option><option value="xquery">XQuery</option><option value="yaml">YAML</option><option value="z80">Z80</option></select>
664 <option value="apl">APL</option><option value="asterisk">Asterisk</option><option value="clike">C</option><option value="clike">C++</option><option value="cobol">Cobol</option><option value="clike">Java</option><option value="clike">C#</option><option value="clike">Scala</option><option value="clojure">Clojure</option><option value="coffeescript">CoffeeScript</option><option value="commonlisp">Common Lisp</option><option value="css">CSS</option><option value="d">D</option><option value="diff">diff</option><option value="dtd">DTD</option><option value="dylan">Dylan</option><option value="ecl">ECL</option><option value="eiffel">Eiffel</option><option value="erlang">Erlang</option><option value="fortran">Fortran</option><option value="mllike">F#</option><option value="gas">Gas</option><option value="go">GO</option><option value="gherkin">Gherkin</option><option value="go">Go</option><option value="groovy">Groovy</option><option value="haml">HAML</option><option value="haskell">Haskell</option><option value="haxe">Haxe</option><option value="htmlembedded">ASP.NET</option><option value="htmlembedded">Embedded Javascript</option><option value="htmlembedded">JavaServer Pages</option><option value="htmlmixed">HTML</option><option value="http">HTTP</option><option value="jade">Jade</option><option value="javascript">JavaScript</option><option value="javascript">JSON</option><option value="javascript">TypeScript</option><option value="jinja2">Jinja2</option><option value="julia">Julia</option><option value="less">LESS</option><option value="livescript">LiveScript</option><option value="lua">Lua</option><option value="markdown">Markdown (GitHub-flavour)</option><option value="mirc">mIRC</option><option value="nginx">Nginx</option><option value="ntriples">NTriples</option><option value="ocaml">OCaml</option><option value="mllike">OCaml</option><option value="octave">Octave</option><option value="pascal">Pascal</option><option value="pegjs">PEG.js</option><option value="perl">Perl</option><option value="php">PHP</option><option value="pig">Pig</option><option value="null">Plain Text</option><option value="properties">Properties files</option><option value="python" selected="selected">Python</option><option value="puppet">Puppet</option><option value="r">R</option><option value="rst">reStructuredText</option><option value="ruby">Ruby</option><option value="rust">Rust</option><option value="sass">Sass</option><option value="scheme">Scheme</option><option value="css">SCSS</option><option value="shell">Shell</option><option value="sieve">Sieve</option><option value="smalltalk">Smalltalk</option><option value="smarty">Smarty</option><option value="smartymixed">SmartyMixed</option><option value="solr">Solr</option><option value="sparql">SPARQL</option><option value="sql">SQL</option><option value="sql">MariaDB</option><option value="stex">sTeX</option><option value="stex">LaTeX</option><option value="verilog">SystemVerilog</option><option value="tcl">Tcl</option><option value="tiddlywiki">TiddlyWiki </option><option value="tiki">Tiki wiki</option><option value="toml">TOML</option><option value="turtle">Turtle</option><option value="vb">VB.NET</option><option value="vbscript">VBScript</option><option value="velocity">Velocity</option><option value="verilog">Verilog</option><option value="xml">XML</option><option value="xml">HTML</option><option value="xquery">XQuery</option><option value="yaml">YAML</option><option value="z80">Z80</option></select>
665 <script>
665 <script>
666 $(document).ready(function() {
666 $(document).ready(function() {
667 $('#set_mode').select2({
667 $('#set_mode').select2({
668 containerCssClass: 'drop-menu',
668 containerCssClass: 'drop-menu',
669 dropdownCssClass: 'drop-menu-dropdown',
669 dropdownCssClass: 'drop-menu-dropdown',
670 dropdownAutoWidth: true
670 dropdownAutoWidth: true
671 });
671 });
672 });
672 });
673 </script>
673 </script>
674
674
675 <label for="line_wrap">line wraps</label>
675 <label for="line_wrap">line wraps</label>
676 <div class="select2-container drop-menu" id="s2id_line_wrap"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">off</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen">line wraps</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown"> <div class="select2-search select2-search-hidden select2-offscreen"> <label for="s2id_autogen3_search" class="select2-offscreen">line wraps</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="line_wrap" name="line_wrap" tabindex="-1" title="line wraps" style="display: none;">
676 <div class="select2-container drop-menu" id="s2id_line_wrap"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">off</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen">line wraps</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown"> <div class="select2-search select2-search-hidden select2-offscreen"> <label for="s2id_autogen3_search" class="select2-offscreen">line wraps</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="line_wrap" name="line_wrap" tabindex="-1" title="line wraps" style="display: none;">
677 <option value="on">on</option>
677 <option value="on">on</option>
678 <option selected="selected" value="off">off</option>
678 <option selected="selected" value="off">off</option>
679 </select>
679 </select>
680 <script>
680 <script>
681 $(document).ready(function() {
681 $(document).ready(function() {
682 $('#line_wrap').select2({
682 $('#line_wrap').select2({
683 containerCssClass: 'drop-menu',
683 containerCssClass: 'drop-menu',
684 dropdownCssClass: 'drop-menu-dropdown',
684 dropdownCssClass: 'drop-menu-dropdown',
685 dropdownAutoWidth: true,
685 dropdownAutoWidth: true,
686 minimumResultsForSearch: -1
686 minimumResultsForSearch: -1
687
687
688 });
688 });
689 });
689 });
690 </script>
690 </script>
691
691
692 <div id="render_preview" class="btn btn-mini hidden disabled">Preview</div>
692 <div id="render_preview" class="btn btn-mini hidden disabled">Preview</div>
693 </div>
693 </div>
694 </div>
694 </div>
695 <div id="editor_container">
695 <div id="editor_container">
696 <pre id="editor_pre"></pre>
696 <pre id="editor_pre"></pre>
697 <textarea id="editor" name="content" style="display: none;"># -*- coding: utf-8 -*-
697 <textarea id="editor" name="content" style="display: none;"># -*- coding: utf-8 -*-
698
698
699 # Published under Commercial License.
699 # Published under Commercial License.
700 # Read the full license text at https://rhodecode.com/licenses.
700 # Read the full license text at https://rhodecode.com/licenses.
701 """
701 """
702 rhodecode.websetup
702 rhodecode.websetup
703 ~~~~~~~~~~~~~~~~~~
703 ~~~~~~~~~~~~~~~~~~
704
704
705 Weboperations and setup for rhodecode
705 Weboperations and setup for rhodecode
706
706
707 :created_on: Dec 11, 2010
707 :created_on: Dec 11, 2010
708 :author: marcink
708 :author: marcink
709 :copyright: (c) 2013-2015 RhodeCode GmbH.
709 :copyright: (c) 2013-2015 RhodeCode GmbH.
710 :license: Commercial License, see LICENSE for more details.
710 :license: Commercial License, see LICENSE for more details.
711 """
711 """
712
712
713 import logging
713 import logging
714
714
715 from rhodecode.config.environment import load_environment
715 from rhodecode.config.environment import load_environment
716 from rhodecode.lib.db_manage import DbManage
716 from rhodecode.lib.db_manage import DbManage
717 from rhodecode.model.meta import Session
717 from rhodecode.model.meta import Session
718
718
719
719
720 log = logging.getLogger(__name__)
720 log = logging.getLogger(__name__)
721
721
722
722
723 def setup_app(command, conf, vars):
723 def setup_app(command, conf, vars):
724 """Place any commands to setup rhodecode here"""
724 """Place any commands to setup rhodecode here"""
725 dbconf = conf['sqlalchemy.db1.url']
725 dbconf = conf['sqlalchemy.db1.url']
726 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=conf['here'],
726 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=conf['here'],
727 tests=False, cli_args=command.options.__dict__)
727 tests=False, cli_args=command.options.__dict__)
728 dbmanage.create_tables(override=True)
728 dbmanage.create_tables(override=True)
729 dbmanage.set_db_version()
729 dbmanage.set_db_version()
730 opts = dbmanage.config_prompt(None)
730 opts = dbmanage.config_prompt(None)
731 dbmanage.create_settings(opts)
731 dbmanage.create_settings(opts)
732 dbmanage.create_default_user()
732 dbmanage.create_default_user()
733 dbmanage.admin_prompt()
733 dbmanage.admin_prompt()
734 dbmanage.create_permissions()
734 dbmanage.create_permissions()
735 dbmanage.populate_default_permissions()
735 dbmanage.populate_default_permissions()
736 Session().commit()
736 Session().commit()
737 load_environment(conf.global_conf, conf.local_conf, initial=True)
737 load_environment(conf.global_conf, conf.local_conf, initial=True)
738 </textarea><div class="CodeMirror cm-s-default CodeMirror-focused"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 5px; left: 34px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="display: block; bottom: 0px; min-width: 18px;"><div style="min-width: 1px; height: 554px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 579.350463867188px; margin-left: 29px; min-height: 554px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div style="width: 50px; height: 50px; overflow-x: scroll;"></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-comment"># -*- coding: utf-8 -*-</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-comment"># Published under Commercial License.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-comment"># Read the full license text at https://rhodecode.com/licenses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-string">rhodecode.websetup</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre><span class="cm-string">~~~~~~~~~~~~~~~~~~</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-string">Weboperations and setup for rhodecode</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string">:created_on: Dec 11, 2010</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string">:author: marcink</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string">:copyright: (c) 2013-2015 RhodeCode GmbH.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string">:license: Commercial License, see LICENSE for more details.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">logging</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">config</span>.<span class="cm-variable">environment</span> <span class="cm-keyword">import</span> <span class="cm-variable">load_environment</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">lib</span>.<span class="cm-variable">db_manage</span> <span class="cm-keyword">import</span> <span class="cm-variable">DbManage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">model</span>.<span class="cm-variable">meta</span> <span class="cm-keyword">import</span> <span class="cm-variable">Session</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre><span class="cm-variable">log</span> = <span class="cm-variable">logging</span>.<span class="cm-variable">getLogger</span>(<span class="cm-variable">__name__</span>) # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre><span class="cm-keyword">def</span> <span class="cm-def">setup_app</span>(<span class="cm-variable">command</span>, <span class="cm-variable">conf</span>, <span class="cm-builtin">vars</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-string">"""Place any commands to setup rhodecode here"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre> <span class="cm-variable">dbconf</span> = <span class="cm-variable">conf</span>[<span class="cm-string">'sqlalchemy.db1.url'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-variable">dbmanage</span> = <span class="cm-variable">DbManage</span>(<span class="cm-variable">log_sql</span>=<span class="cm-builtin">True</span>, <span class="cm-variable">dbconf</span>=<span class="cm-variable">dbconf</span>, <span class="cm-variable">root</span>=<span class="cm-variable">conf</span>[<span class="cm-string">'here'</span>],</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-variable">tests</span>=<span class="cm-builtin">False</span>, <span class="cm-variable">cli_args</span>=<span class="cm-variable">command</span>.<span class="cm-variable">options</span>.<span class="cm-variable">__dict__</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_tables</span>(<span class="cm-variable">override</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">set_db_version</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-variable">opts</span> = <span class="cm-variable">dbmanage</span>.<span class="cm-variable">config_prompt</span>(<span class="cm-builtin">None</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_settings</span>(<span class="cm-variable">opts</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_default_user</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">admin_prompt</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">populate_default_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">Session</span>().<span class="cm-variable">commit</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">load_environment</span>(<span class="cm-variable">conf</span>.<span class="cm-variable">global_conf</span>, <span class="cm-variable">conf</span>.<span class="cm-variable">local_conf</span>, <span class="cm-variable">initial</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div></div><div class="CodeMirror-cursor" style="left: 4px; top: 0px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 554px;"></div><div class="CodeMirror-gutters" style="height: 554px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
738 </textarea><div class="CodeMirror cm-s-default CodeMirror-focused"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 5px; left: 34px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="display: block; bottom: 0px; min-width: 18px;"><div style="min-width: 1px; height: 554px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 579.350463867188px; margin-left: 29px; min-height: 554px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div style="width: 50px; height: 50px; overflow-x: scroll;"></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-comment"># -*- coding: utf-8 -*-</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-comment"># Published under Commercial License.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-comment"># Read the full license text at https://rhodecode.com/licenses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-string">rhodecode.websetup</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre><span class="cm-string">~~~~~~~~~~~~~~~~~~</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-string">Weboperations and setup for rhodecode</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string">:created_on: Dec 11, 2010</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string">:author: marcink</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string">:copyright: (c) 2013-2015 RhodeCode GmbH.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string">:license: Commercial License, see LICENSE for more details.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">logging</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">config</span>.<span class="cm-variable">environment</span> <span class="cm-keyword">import</span> <span class="cm-variable">load_environment</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">lib</span>.<span class="cm-variable">db_manage</span> <span class="cm-keyword">import</span> <span class="cm-variable">DbManage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">model</span>.<span class="cm-variable">meta</span> <span class="cm-keyword">import</span> <span class="cm-variable">Session</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre><span class="cm-variable">log</span> = <span class="cm-variable">logging</span>.<span class="cm-variable">getLogger</span>(<span class="cm-variable">__name__</span>) # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre><span class="cm-keyword">def</span> <span class="cm-def">setup_app</span>(<span class="cm-variable">command</span>, <span class="cm-variable">conf</span>, <span class="cm-builtin">vars</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-string">"""Place any commands to setup rhodecode here"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre> <span class="cm-variable">dbconf</span> = <span class="cm-variable">conf</span>[<span class="cm-string">'sqlalchemy.db1.url'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-variable">dbmanage</span> = <span class="cm-variable">DbManage</span>(<span class="cm-variable">log_sql</span>=<span class="cm-builtin">True</span>, <span class="cm-variable">dbconf</span>=<span class="cm-variable">dbconf</span>, <span class="cm-variable">root</span>=<span class="cm-variable">conf</span>[<span class="cm-string">'here'</span>],</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-variable">tests</span>=<span class="cm-builtin">False</span>, <span class="cm-variable">cli_args</span>=<span class="cm-variable">command</span>.<span class="cm-variable">options</span>.<span class="cm-variable">__dict__</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_tables</span>(<span class="cm-variable">override</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">set_db_version</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-variable">opts</span> = <span class="cm-variable">dbmanage</span>.<span class="cm-variable">config_prompt</span>(<span class="cm-builtin">None</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_settings</span>(<span class="cm-variable">opts</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_default_user</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">admin_prompt</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">populate_default_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">Session</span>().<span class="cm-variable">commit</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">load_environment</span>(<span class="cm-variable">conf</span>.<span class="cm-variable">global_conf</span>, <span class="cm-variable">conf</span>.<span class="cm-variable">local_conf</span>, <span class="cm-variable">initial</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div></div><div class="CodeMirror-cursor" style="left: 4px; top: 0px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 554px;"></div><div class="CodeMirror-gutters" style="height: 554px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
739 <div id="editor_preview"></div>
739 <div id="editor_preview"></div>
740 </div>
740 </div>
741 <div class="message">
741 <div class="message">
742 <label class="codeblock-label">Commit Message</label>
742 <label class="codeblock-label">Commit Message</label>
743 <textarea id="commit" name="message" placeholder="Edited file rhodecode/websetup.py via RhodeCode"></textarea>
743 <textarea id="commit" name="message" placeholder="Edited file rhodecode/websetup.py via RhodeCode"></textarea>
744 </div>
744 </div>
745 </div>
745 </div>
746
746
747
747
748
748
749
749
750
750
751
751
752 <!--
752 <!--
753 Commit with comments
753 Commit with comments
754 -->
754 -->
755
755
756 <h2>Commit with comments</h2>
756 <h2>Commit with comments</h2>
757
757
758 <div class="diff-container" id="diff-container-140360037209920">
758 <div class="diff-container" id="diff-container-140360037209920">
759 <div id="c-4e5ee86997c6-7046e4320b26_target"></div>
759 <div id="c-4e5ee86997c6-7046e4320b26_target"></div>
760 <div id="c-4e5ee86997c6-7046e4320b26" class="diffblock margined comm">
760 <div id="c-4e5ee86997c6-7046e4320b26" class="diffblock margined comm">
761 <div class="code-header">
761 <div class="code-header">
762 <div title="Go back to changed files overview">
762 <div title="Go back to changed files overview">
763 <a href="#changes_box">
763 <a href="#changes_box">
764 <i class="icon-circle-arrow-up"></i>
764 <i class="icon-circle-arrow-up"></i>
765 </a>
765 </a>
766 </div>
766 </div>
767 <div class="changeset_header">
767 <div class="changeset_header">
768 <div class="changeset_file">
768 <div class="changeset_file">
769 <i class="icon-file"></i>
769 <i class="icon-file"></i>
770 <a href="/andersonsantos/rhodecode-dev-fork/files/4e5ee86997c64981d85cf62283af448624e26929/rhodecode/tests/functional/test_compare_local.py">rhodecode/tests/functional/test_compare_local.py</a>
770 <a href="/andersonsantos/rhodecode-dev-fork/files/4e5ee86997c64981d85cf62283af448624e26929/rhodecode/tests/functional/test_compare_local.py">rhodecode/tests/functional/test_compare_local.py</a>
771 </div>
771 </div>
772 <div class="diff-actions">
772 <div class="diff-actions">
773 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full diff for this file">
773 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full diff for this file">
774 <img class="icon" src="/images/icons/page_white_go.png">
774 <img class="icon" src="/images/icons/page_white_go.png">
775 </a>
775 </a>
776 <a href="/andersonsantos/rhodecode-dev-fork/diff-2way/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full side-by-side diff for this file">
776 <a href="/andersonsantos/rhodecode-dev-fork/diff-2way/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full side-by-side diff for this file">
777 <img class="icon" src="/images/icons/application_double.png">
777 <img class="icon" src="/images/icons/application_double.png">
778 </a>
778 </a>
779 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=raw&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Raw diff">
779 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=raw&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Raw diff">
780 <img class="icon" src="/images/icons/page_white.png">
780 <img class="icon" src="/images/icons/page_white.png">
781 </a>
781 </a>
782 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=download&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Download diff">
782 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=download&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Download diff">
783 <img class="icon" src="/images/icons/page_save.png">
783 <img class="icon" src="/images/icons/page_save.png">
784 </a>
784 </a>
785 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=WS%3A1&amp;c-4e5ee86997c6-7046e4320b26=C%3A3#c-4e5ee86997c6-7046e4320b26" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
785 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=WS%3A1&amp;c-4e5ee86997c6-7046e4320b26=C%3A3#c-4e5ee86997c6-7046e4320b26" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
786 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=C%3A6#c-4e5ee86997c6-7046e4320b26" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
786 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=C%3A6#c-4e5ee86997c6-7046e4320b26" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
787 </div>
787 </div>
788 <span>
788 <span>
789 <label>
789 <label>
790 Show inline comments
790 Show inline comments
791 <input checked="checked" class="show-inline-comments" id="" id_for="c-4e5ee86997c6-7046e4320b26" name="" type="checkbox" value="1">
791 <input checked="checked" class="show-inline-comments" id="" id_for="c-4e5ee86997c6-7046e4320b26" name="" type="checkbox" value="1">
792 </label>
792 </label>
793 </span>
793 </span>
794 </div>
794 </div>
795 </div>
795 </div>
796 <div class="code-body">
796 <div class="code-body">
797 <div class="full_f_path" path="rhodecode/tests/functional/test_compare_local.py"></div>
797 <div class="full_f_path" path="rhodecode/tests/functional/test_compare_local.py"></div>
798 <table class="code-difftable">
798 <table class="code-difftable">
799 <tbody><tr class="line context">
799 <tbody><tr class="line context">
800 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
800 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
801 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
801 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
802 <td class="code ">
802 <td class="code ">
803 <pre>@@ -59,7 +59,7 @@
803 <pre>@@ -59,7 +59,7 @@
804 </pre>
804 </pre>
805 </td>
805 </td>
806 </tr>
806 </tr>
807 <tr class="line unmod">
807 <tr class="line unmod">
808 <td id="rhodecodetestsfunctionaltest_compare_localpy_o59" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o59">59</a></td>
808 <td id="rhodecodetestsfunctionaltest_compare_localpy_o59" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o59">59</a></td>
809 <td id="rhodecodetestsfunctionaltest_compare_localpy_n59" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n59">59</a></td>
809 <td id="rhodecodetestsfunctionaltest_compare_localpy_n59" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n59">59</a></td>
810 <td class="code ">
810 <td class="code ">
811 <pre> 'tag': 'v0.2.0',
811 <pre> 'tag': 'v0.2.0',
812 </pre>
812 </pre>
813 </td>
813 </td>
814 </tr>
814 </tr>
815 <tr class="line unmod">
815 <tr class="line unmod">
816 <td id="rhodecodetestsfunctionaltest_compare_localpy_o60" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o60">60</a></td>
816 <td id="rhodecodetestsfunctionaltest_compare_localpy_o60" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o60">60</a></td>
817 <td id="rhodecodetestsfunctionaltest_compare_localpy_n60" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n60">60</a></td>
817 <td id="rhodecodetestsfunctionaltest_compare_localpy_n60" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n60">60</a></td>
818 <td class="code ">
818 <td class="code ">
819 <pre> 'branch': 'default',
819 <pre> 'branch': 'default',
820 </pre>
820 </pre>
821 </td>
821 </td>
822 </tr>
822 </tr>
823 <tr class="line unmod">
823 <tr class="line unmod">
824 <td id="rhodecodetestsfunctionaltest_compare_localpy_o61" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o61">61</a></td>
824 <td id="rhodecodetestsfunctionaltest_compare_localpy_o61" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o61">61</a></td>
825 <td id="rhodecodetestsfunctionaltest_compare_localpy_n61" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n61">61</a></td>
825 <td id="rhodecodetestsfunctionaltest_compare_localpy_n61" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n61">61</a></td>
826 <td class="code ">
826 <td class="code ">
827 <pre> 'response': # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.
827 <pre> 'response': # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.
828 </pre>
828 </pre>
829 </td>
829 </td>
830 </tr>
830 </tr>
831 <tr class="line del">
831 <tr class="line del">
832 <td id="rhodecodetestsfunctionaltest_compare_localpy_o62" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o62">62</a></td>
832 <td id="rhodecodetestsfunctionaltest_compare_localpy_o62" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o62">62</a></td>
833 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
833 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
834 <td class="code ">
834 <td class="code ">
835 <pre> '147 files changed: 5700 inserted, 10176 deleted'
835 <pre> '147 files changed: 5700 inserted, 10176 deleted'
836 </pre>
836 </pre>
837 </td>
837 </td>
838 </tr>
838 </tr>
839 <tr class="line add">
839 <tr class="line add">
840 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
840 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
841 <td id="rhodecodetestsfunctionaltest_compare_localpy_n62" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n62">62</a></td>
841 <td id="rhodecodetestsfunctionaltest_compare_localpy_n62" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n62">62</a></td>
842 <td class="code ">
842 <td class="code ">
843 <pre><ins> </ins> '147 files changed: 5700 inserted, 10176 deleted'
843 <pre><ins> </ins> '147 files changed: 5700 inserted, 10176 deleted'
844 </pre>
844 </pre>
845 </td>
845 </td>
846 </tr>
846 </tr>
847 <tr class="line unmod">
847 <tr class="line unmod">
848 <td id="rhodecodetestsfunctionaltest_compare_localpy_o63" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o63">63</a></td>
848 <td id="rhodecodetestsfunctionaltest_compare_localpy_o63" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o63">63</a></td>
849 <td id="rhodecodetestsfunctionaltest_compare_localpy_n63" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n63">63</a></td>
849 <td id="rhodecodetestsfunctionaltest_compare_localpy_n63" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n63">63</a></td>
850 <td class="code ">
850 <td class="code ">
851 <pre> },
851 <pre> },
852 </pre>
852 </pre>
853 </td>
853 </td>
854 </tr>
854 </tr>
855 <tr class="line unmod">
855 <tr class="line unmod">
856 <td id="rhodecodetestsfunctionaltest_compare_localpy_o64" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o64">64</a></td>
856 <td id="rhodecodetestsfunctionaltest_compare_localpy_o64" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o64">64</a></td>
857 <td id="rhodecodetestsfunctionaltest_compare_localpy_n64" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n64">64</a></td>
857 <td id="rhodecodetestsfunctionaltest_compare_localpy_n64" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n64">64</a></td>
858 <td class="code ">
858 <td class="code ">
859 <pre> 'git': {
859 <pre> 'git': {
860 </pre>
860 </pre>
861 </td>
861 </td>
862 </tr>
862 </tr>
863 <tr class="line unmod">
863 <tr class="line unmod">
864 <td id="rhodecodetestsfunctionaltest_compare_localpy_o65" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o65">65</a></td>
864 <td id="rhodecodetestsfunctionaltest_compare_localpy_o65" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o65">65</a></td>
865 <td id="rhodecodetestsfunctionaltest_compare_localpy_n65" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n65">65</a></td>
865 <td id="rhodecodetestsfunctionaltest_compare_localpy_n65" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n65">65</a></td>
866 <td class="code ">
866 <td class="code ">
867 <pre> 'tag': 'v0.2.2',
867 <pre> 'tag': 'v0.2.2',
868 </pre>
868 </pre>
869 </td>
869 </td>
870 </tr>
870 </tr>
871 <tr class="line context">
871 <tr class="line context">
872 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
872 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
873 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
873 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
874 <td class="code ">
874 <td class="code ">
875 <pre>@@ -77,9 +77,11 @@
875 <pre>@@ -77,9 +77,11 @@
876 </pre>
876 </pre>
877 </td>
877 </td>
878 </tr>
878 </tr>
879 <tr class="line unmod">
879 <tr class="line unmod">
880 <td id="rhodecodetestsfunctionaltest_compare_localpy_o77" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o77">77</a></td>
880 <td id="rhodecodetestsfunctionaltest_compare_localpy_o77" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o77">77</a></td>
881 <td id="rhodecodetestsfunctionaltest_compare_localpy_n77" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n77">77</a></td>
881 <td id="rhodecodetestsfunctionaltest_compare_localpy_n77" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n77">77</a></td>
882 <td class="code ">
882 <td class="code ">
883 <pre> target_ref=revisions[backend.alias]['tag'],
883 <pre> target_ref=revisions[backend.alias]['tag'],
884 </pre>
884 </pre>
885 </td>
885 </td>
886 </tr>
886 </tr>
887 <tr class="line unmod">
887 <tr class="line unmod">
888 <td id="rhodecodetestsfunctionaltest_compare_localpy_o78" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o78">78</a></td>
888 <td id="rhodecodetestsfunctionaltest_compare_localpy_o78" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o78">78</a></td>
889 <td id="rhodecodetestsfunctionaltest_compare_localpy_n78" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n78">78</a></td>
889 <td id="rhodecodetestsfunctionaltest_compare_localpy_n78" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n78">78</a></td>
890 <td class="code ">
890 <td class="code ">
891 <pre> ))
891 <pre> ))
892 </pre>
892 </pre>
893 </td>
893 </td>
894 </tr><tr id="comment-tr-3754" class="inline-comments"><td></td><td></td><td>
894 </tr><tr id="comment-tr-3754" class="inline-comments"><td></td><td></td><td>
895
895
896 <div class="comment" id="comment-3754" line="n78">
896 <div class="comment" id="comment-3754" line="n78">
897 <div class="comment-wrapp">
897 <div class="comment-wrapp">
898 <div class="meta">
898 <div class="meta">
899 <span class="gravatar">
899 <span class="gravatar">
900 <img src="https://secure.gravatar.com/avatar/72706ebd30734451af9ff3fb59f05ff1?d=identicon&amp;s=40" height="20" width="20">
900 <img src="https://secure.gravatar.com/avatar/72706ebd30734451af9ff3fb59f05ff1?d=identicon&amp;s=40" height="20" width="20">
901 </span>
901 </span>
902 <span class="user">
902 <span class="user">
903 anderson
903 anderson
904 </span>
904 </span>
905 <span class="date">
905 <span class="date">
906 just now |
906 just now |
907 </span>
907 </span>
908 <span class="status-change">
908 <span class="status-change">
909 Comment on commit
909 Comment on commit
910 </span>
910 </span>
911 <a class="permalink" href="#comment-3754">ΒΆ</a>
911 <a class="permalink" href="#comment-3754">ΒΆ</a>
912 </div>
912 </div>
913 <div class="text">
913 <div class="text">
914 <div class="rst-block"><p>commented line
914 <div class="rst-block"><p>commented line
915 with multiple lines</p>
915 with multiple lines</p>
916 </div>
916 </div>
917 </div>
917 </div>
918 </div>
918 </div>
919 </div><div class="add-comment"><span class="btn btn-default">Add another comment</span></div>
919 </div><div class="add-comment"><span class="btn btn-default">Add another comment</span></div>
920
920
921 </td></tr>
921 </td></tr>
922 <tr class="line unmod">
922 <tr class="line unmod">
923 <td id="rhodecodetestsfunctionaltest_compare_localpy_o79" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o79">79</a></td>
923 <td id="rhodecodetestsfunctionaltest_compare_localpy_o79" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o79">79</a></td>
924 <td id="rhodecodetestsfunctionaltest_compare_localpy_n79" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n79">79</a></td>
924 <td id="rhodecodetestsfunctionaltest_compare_localpy_n79" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n79">79</a></td>
925 <td class="code ">
925 <td class="code ">
926 <pre></pre>
926 <pre></pre>
927 </td>
927 </td>
928 </tr>
928 </tr>
929 <tr class="line del form-open hl-comment">
929 <tr class="line del form-open hl-comment">
930 <td id="rhodecodetestsfunctionaltest_compare_localpy_o80" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o80">80</a></td>
930 <td id="rhodecodetestsfunctionaltest_compare_localpy_o80" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o80">80</a></td>
931 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
931 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
932 <td class="code ">
932 <td class="code ">
933 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
933 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
934 </pre>
934 </pre>
935 </td>
935 </td>
936 </tr><tr id="comment-tr-undefined" class="comment-form-inline"><td></td><td></td><td>
936 </tr><tr id="comment-tr-undefined" class="comment-form-inline"><td></td><td></td><td>
937 <div class="comment-inline-form ac">
937 <div class="comment-inline-form ac">
938 <div class="overlay"><div class="overlay-text">Submitting...</div></div>
938 <div class="overlay"><div class="overlay-text">Submitting...</div></div>
939 <form action="#" class="inline-form" method="get">
939 <form action="#" class="inline-form" method="get">
940 <div id="edit-container_o80" class="clearfix">
940 <div id="edit-container_o80" class="clearfix">
941 <div class="comment-title pull-left">
941 <div class="comment-title pull-left">
942 Commenting on line o80.
942 Commenting on line o80.
943 </div>
943 </div>
944 <div class="comment-help pull-right">
944 <div class="comment-help pull-right">
945 Comments parsed using <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">RST</a> syntax with <span class="tooltip" title="Use @username inside this text to send notification to this RhodeCode user">@mention</span> support.
945 Comments parsed using <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">RST</a> syntax with <span class="tooltip" title="Use @username inside this text to send notification to this RhodeCode user">@mention</span> support.
946 </div>
946 </div>
947 <div style="clear: both"></div>
947 <div style="clear: both"></div>
948 <textarea id="text_o80" name="text" class="comment-block-ta ac-input" autocomplete="off"></textarea>
948 <textarea id="text_o80" name="text" class="comment-block-ta ac-input" autocomplete="off"></textarea>
949 </div>
949 </div>
950 <div id="preview-container_o80" class="clearfix" style="display: none;">
950 <div id="preview-container_o80" class="clearfix" style="display: none;">
951 <div class="comment-help">
951 <div class="comment-help">
952 Comment preview
952 Comment preview
953 </div>
953 </div>
954 <div id="preview-box_o80" class="preview-box"></div>
954 <div id="preview-box_o80" class="preview-box"></div>
955 </div>
955 </div>
956 <div class="comment-button pull-right">
956 <div class="comment-button pull-right">
957 <input type="hidden" name="f_path" value="rhodecode/tests/functional/test_compare_local.py">
957 <input type="hidden" name="f_path" value="rhodecode/tests/functional/test_compare_local.py">
958 <input type="hidden" name="line" value="o80">
958 <input type="hidden" name="line" value="o80">
959 <div id="preview-btn_o80" class="btn btn-default">Preview</div>
959 <div id="preview-btn_o80" class="btn btn-default">Preview</div>
960 <div id="edit-btn_o80" class="btn" style="display: none;">Edit</div>
960 <div id="edit-btn_o80" class="btn" style="display: none;">Edit</div>
961 <input class="btn btn-success save-inline-form" id="save" name="save" type="submit" value="Comment">
961 <input class="btn btn-success save-inline-form" id="save" name="save" type="submit" value="Comment">
962 </div>
962 </div>
963 <div class="comment-button hide-inline-form-button">
963 <div class="comment-button hide-inline-form-button">
964 <input class="btn hide-inline-form" id="hide-inline-form" name="hide-inline-form" type="reset" value="Cancel">
964 <input class="btn hide-inline-form" id="hide-inline-form" name="hide-inline-form" type="reset" value="Cancel">
965 </div>
965 </div>
966 </form>
966 </form>
967 </div>
967 </div>
968 </td></tr>
968 </td></tr>
969 <tr class="line add">
969 <tr class="line add">
970 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
970 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
971 <td id="rhodecodetestsfunctionaltest_compare_localpy_n80" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n80">80</a></td>
971 <td id="rhodecodetestsfunctionaltest_compare_localpy_n80" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n80">80</a></td>
972 <td class="code ">
972 <td class="code ">
973 <pre> response.mustcontain('%s@%s' % (
973 <pre> response.mustcontain('%s@%s' % (
974 </pre>
974 </pre>
975 </td>
975 </td>
976 </tr>
976 </tr>
977 <tr class="line add">
977 <tr class="line add">
978 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
978 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
979 <td id="rhodecodetestsfunctionaltest_compare_localpy_n81" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n81">81</a></td>
979 <td id="rhodecodetestsfunctionaltest_compare_localpy_n81" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n81">81</a></td>
980 <td class="code ">
980 <td class="code ">
981 <pre> backend.repo_name,
981 <pre> backend.repo_name,
982 </pre>
982 </pre>
983 </td>
983 </td>
984 </tr>
984 </tr>
985 <tr class="line unmod">
985 <tr class="line unmod">
986 <td id="rhodecodetestsfunctionaltest_compare_localpy_o81" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o81">81</a></td>
986 <td id="rhodecodetestsfunctionaltest_compare_localpy_o81" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o81">81</a></td>
987 <td id="rhodecodetestsfunctionaltest_compare_localpy_n82" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n82">82</a></td>
987 <td id="rhodecodetestsfunctionaltest_compare_localpy_n82" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n82">82</a></td>
988 <td class="code ">
988 <td class="code ">
989 <pre> revisions[backend.alias]['branch']))
989 <pre> revisions[backend.alias]['branch']))
990 </pre>
990 </pre>
991 </td>
991 </td>
992 </tr>
992 </tr>
993 <tr class="line del">
993 <tr class="line del">
994 <td id="rhodecodetestsfunctionaltest_compare_localpy_o82" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o82">82</a></td>
994 <td id="rhodecodetestsfunctionaltest_compare_localpy_o82" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o82">82</a></td>
995 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
995 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
996 <td class="code ">
996 <td class="code ">
997 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
997 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
998 </pre>
998 </pre>
999 </td>
999 </td>
1000 </tr>
1000 </tr>
1001 <tr class="line add">
1001 <tr class="line add">
1002 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1002 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1003 <td id="rhodecodetestsfunctionaltest_compare_localpy_n83" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n83">83</a></td>
1003 <td id="rhodecodetestsfunctionaltest_compare_localpy_n83" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n83">83</a></td>
1004 <td class="code ">
1004 <td class="code ">
1005 <pre> response.mustcontain('%s@%s' % (
1005 <pre> response.mustcontain('%s@%s' % (
1006 </pre>
1006 </pre>
1007 </td>
1007 </td>
1008 </tr>
1008 </tr>
1009 <tr class="line add">
1009 <tr class="line add">
1010 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1010 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1011 <td id="rhodecodetestsfunctionaltest_compare_localpy_n84" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n84">84</a></td>
1011 <td id="rhodecodetestsfunctionaltest_compare_localpy_n84" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n84">84</a></td>
1012 <td class="code ">
1012 <td class="code ">
1013 <pre> backend.repo_name,
1013 <pre> backend.repo_name,
1014 </pre>
1014 </pre>
1015 </td>
1015 </td>
1016 </tr>
1016 </tr>
1017 <tr class="line unmod">
1017 <tr class="line unmod">
1018 <td id="rhodecodetestsfunctionaltest_compare_localpy_o83" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o83">83</a></td>
1018 <td id="rhodecodetestsfunctionaltest_compare_localpy_o83" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o83">83</a></td>
1019 <td id="rhodecodetestsfunctionaltest_compare_localpy_n85" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n85">85</a></td>
1019 <td id="rhodecodetestsfunctionaltest_compare_localpy_n85" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n85">85</a></td>
1020 <td class="code ">
1020 <td class="code ">
1021 <pre> revisions[backend.alias]['tag']))
1021 <pre> revisions[backend.alias]['tag']))
1022 </pre>
1022 </pre>
1023 </td>
1023 </td>
1024 </tr>
1024 </tr>
1025 <tr class="line unmod">
1025 <tr class="line unmod">
1026 <td id="rhodecodetestsfunctionaltest_compare_localpy_o84" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o84">84</a></td>
1026 <td id="rhodecodetestsfunctionaltest_compare_localpy_o84" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o84">84</a></td>
1027 <td id="rhodecodetestsfunctionaltest_compare_localpy_n86" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n86">86</a></td>
1027 <td id="rhodecodetestsfunctionaltest_compare_localpy_n86" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n86">86</a></td>
1028 <td class="code ">
1028 <td class="code ">
1029 <pre> response.mustcontain(revisions[backend.alias]['response'])
1029 <pre> response.mustcontain(revisions[backend.alias]['response'])
1030 </pre>
1030 </pre>
1031 </td>
1031 </td>
1032 </tr>
1032 </tr>
1033 <tr class="line unmod">
1033 <tr class="line unmod">
1034 <td id="rhodecodetestsfunctionaltest_compare_localpy_o85" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o85">85</a></td>
1034 <td id="rhodecodetestsfunctionaltest_compare_localpy_o85" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o85">85</a></td>
1035 <td id="rhodecodetestsfunctionaltest_compare_localpy_n87" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n87">87</a></td>
1035 <td id="rhodecodetestsfunctionaltest_compare_localpy_n87" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n87">87</a></td>
1036 <td class="code ">
1036 <td class="code ">
1037 <pre></pre>
1037 <pre></pre>
1038 </td>
1038 </td>
1039 </tr>
1039 </tr>
1040 </tbody></table>
1040 </tbody></table>
1041 </div>
1041 </div>
1042 </div>
1042 </div>
1043 </div>
1043 </div>
1044
1044
1045
1045
1046
1046
1047 <!--
1047 <!--
1048 Side-by-side diff
1048 Side-by-side diff
1049 -->
1049 -->
1050
1050
1051 <h2>Side-by-side diff</h2>
1051 <h2>Side-by-side diff</h2>
1052
1052
1053 <div class="box">
1053 <div class="box">
1054 <div class="diff-container" style="overflow-x: hidden">
1054 <div class="diff-container" style="overflow-x: hidden">
1055 <div class="diffblock comm" style="margin:3px; padding:1px">
1055 <div class="diffblock comm" style="margin:3px; padding:1px">
1056 <div class="code-header">
1056 <div class="code-header">
1057 <div class="changeset_header">
1057 <div class="changeset_header">
1058 <div class="changeset_file">
1058 <div class="changeset_file">
1059 <i class="icon-file"></i>
1059 <i class="icon-file"></i>
1060 <a href="/pygments/files/ea295cfb622620f5ba13e226ec531e3fe5296399/tests/test_basic_api.py">tests/test_basic_api.py</a>
1060 <a href="/pygments/files/ea295cfb622620f5ba13e226ec531e3fe5296399/tests/test_basic_api.py">tests/test_basic_api.py</a>
1061 [mode: <span id="selected_mode">python</span>]
1061 [mode: <span id="selected_mode">python</span>]
1062 </div>
1062 </div>
1063 <div class="diff-actions">
1063 <div class="diff-actions">
1064 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full diff for this file">
1064 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full diff for this file">
1065 <img class="icon" src="/images/icons/page_white_go.png">
1065 <img class="icon" src="/images/icons/page_white_go.png">
1066 </a>
1066 </a>
1067 <a href="/pygments/diff-2way/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full side-by-side diff for this file" tt_title="Show full side-by-side diff for this file">
1067 <a href="/pygments/diff-2way/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full side-by-side diff for this file" tt_title="Show full side-by-side diff for this file">
1068 <img class="icon" src="/images/icons/application_double.png">
1068 <img class="icon" src="/images/icons/application_double.png">
1069 </a>
1069 </a>
1070 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=raw" class="tooltip" title="Raw diff">
1070 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=raw" class="tooltip" title="Raw diff">
1071 <img class="icon" src="/images/icons/page_white.png">
1071 <img class="icon" src="/images/icons/page_white.png">
1072 </a>
1072 </a>
1073 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=download" class="tooltip" title="Download diff">
1073 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=download" class="tooltip" title="Download diff">
1074 <img class="icon" src="/images/icons/page_save.png">
1074 <img class="icon" src="/images/icons/page_save.png">
1075 </a>
1075 </a>
1076 <label><input id="ignorews" name="ignorews" type="checkbox" value="1">ignore white space</label>
1076 <label><input id="ignorews" name="ignorews" type="checkbox" value="1">ignore white space</label>
1077 <label><input id="edit_mode" name="edit_mode" type="checkbox" value="1">turn on edit mode</label>
1077 <label><input id="edit_mode" name="edit_mode" type="checkbox" value="1">turn on edit mode</label>
1078
1078
1079 </div>
1079 </div>
1080 <div style="float: right; padding: 0px 10px 0px 0px">
1080 <div style="float: right; padding: 0px 10px 0px 0px">
1081 r1538:de45f950b669 ... r1539:ea295cfb6226
1081 r1538:de45f950b669 ... r1539:ea295cfb6226
1082 </div>
1082 </div>
1083 </div>
1083 </div>
1084 </div>
1084 </div>
1085 <div id="compare"></div>
1085 <div id="compare"></div>
1086 </div>
1086 </div>
1087 </div>
1087 </div>
1088
1088
1089 <script>
1089 <script>
1090 $(document).ready(function () {
1090 $(document).ready(function () {
1091 var example_lines = '1\n2\n3\n4\n5\n6\n7\n8\n9\n \n';
1091 var example_lines = '1\n2\n3\n4\n5\n6\n7\n8\n9\n \n';
1092
1092
1093 $('#compare').mergely({
1093 $('#compare').mergely({
1094 width: 'auto',
1094 width: 'auto',
1095 height: '600',
1095 height: '600',
1096 fgcolor: {a:'#ddffdd',c:'#cccccc',d:'#ffdddd'},
1096 fgcolor: {a:'#ddffdd',c:'#cccccc',d:'#ffdddd'},
1097 bgcolor: '#fff',
1097 bgcolor: '#fff',
1098 viewport: true,
1098 viewport: true,
1099 cmsettings: {mode: 'text/plain', readOnly: true, lineWrapping: false, lineNumbers: true},
1099 cmsettings: {mode: 'text/plain', readOnly: true, lineWrapping: false, lineNumbers: true},
1100 lhs: function(setValue) {
1100 lhs: function(setValue) {
1101 if("False" == "True"){
1101 if("False" == "True"){
1102 setValue('Binary file')
1102 setValue('Binary file')
1103 }
1103 }
1104 else if("MercurialCommit" == "EmptyCommit"){
1104 else if("MercurialCommit" == "EmptyCommit"){
1105 setValue('');
1105 setValue('');
1106 }
1106 }
1107 else{
1107 else{
1108 var left_value = example_lines.slice(0, 10) +
1108 var left_value = example_lines.slice(0, 10) +
1109 '123456789 '.repeat(10) +
1109 '123456789 '.repeat(10) +
1110 '\n'+
1110 '\n'+
1111 example_lines.slice(10, 20);
1111 example_lines.slice(10, 20);
1112 setValue(left_value + example_lines.repeat(9));
1112 setValue(left_value + example_lines.repeat(9));
1113 }
1113 }
1114
1114
1115 },
1115 },
1116 rhs: function(setValue) {
1116 rhs: function(setValue) {
1117 if("False" == "True"){
1117 if("False" == "True"){
1118 setValue('Binary file')
1118 setValue('Binary file')
1119 }
1119 }
1120 else if("MercurialCommit" == "EmptyCommit"){
1120 else if("MercurialCommit" == "EmptyCommit"){
1121 setValue('');
1121 setValue('');
1122 }
1122 }
1123 else{
1123 else{
1124 var right_value = example_lines +
1124 var right_value = example_lines +
1125 example_lines.slice(0, 8) +
1125 example_lines.slice(0, 8) +
1126 'abcdefghi '.repeat(10) +
1126 'abcdefghi '.repeat(10) +
1127 '\n'+
1127 '\n'+
1128 example_lines.slice(8, 20);
1128 example_lines.slice(8, 20);
1129 setValue(right_value + example_lines.repeat(9));
1129 setValue(right_value + example_lines.repeat(9));
1130 }
1130 }
1131 },
1131 },
1132 });
1132 });
1133
1133
1134 var detected_mode = detectCodeMirrorModeFromExt('test_basic_api.py', true);
1134 var detected_mode = detectCodeMirrorModeFromExt('test_basic_api.py', true);
1135 if(detected_mode){
1135 if(detected_mode){
1136 setCodeMirrorMode($('#compare').mergely('cm', 'lhs'), detected_mode);
1136 setCodeMirrorMode($('#compare').mergely('cm', 'lhs'), detected_mode);
1137 setCodeMirrorMode($('#compare').mergely('cm', 'rhs'), detected_mode);
1137 setCodeMirrorMode($('#compare').mergely('cm', 'rhs'), detected_mode);
1138 $('#selected_mode').html(detected_mode);
1138 $('#selected_mode').html(detected_mode);
1139 }
1139 }
1140
1140
1141 $('#ignorews').change(function(e){
1141 $('#ignorews').change(function(e){
1142 var val = e.currentTarget.checked;
1142 var val = e.currentTarget.checked;
1143 $('#compare').mergely('options', {ignorews: val});
1143 $('#compare').mergely('options', {ignorews: val});
1144 $('#compare').mergely('update');
1144 $('#compare').mergely('update');
1145 })
1145 })
1146 $('#edit_mode').change(function(e){
1146 $('#edit_mode').change(function(e){
1147 var val = !e.currentTarget.checked;
1147 var val = !e.currentTarget.checked;
1148 $('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
1148 $('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
1149 $('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
1149 $('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
1150 $('#compare').mergely('update');
1150 $('#compare').mergely('update');
1151 })
1151 })
1152 });
1152 });
1153 </script>
1153 </script>
1154
1154
1155 </div>
1155 </div>
1156
1156
1157 <!-- end examples -->
1157 <!-- end examples -->
1158
1158
1159 </div>
1159 </div>
1160 </div>
1160 </div>
1161 </div>
1161 </div>
1162 </%def>
1162 </%def>
@@ -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="/images/user30.png" height="16" width="16">
510 <img class="gravatar" src="/_static/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>
@@ -1,64 +1,64 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html>
2 <!DOCTYPE html>
3 <html xmlns="http://www.w3.org/1999/xhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
4 <head>
5 <title>Error - ${c.error_message}</title>
5 <title>Error - ${c.error_message}</title>
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta name="robots" content="index, nofollow"/>
7 <meta name="robots" content="index, nofollow"/>
8 <link rel="icon" href="${h.url('/images/favicon.ico')}" sizes="16x16 32x32" type="image/png" />
8 <link rel="icon" href="${h.asset('images/favicon.ico')}" sizes="16x16 32x32" type="image/png" />
9
9
10
10
11 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
11 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
12 %if c.redirect_time:
12 %if c.redirect_time:
13 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
13 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
14 %endif
14 %endif
15
15
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen"/>
16 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css')}" media="screen"/>
17 <!--[if IE]>
17 <!--[if IE]>
18 <link rel="stylesheet" type="text/css" href="${h.url('/css/ie.css')}" media="screen"/>
18 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css')}" media="screen"/>
19 <![endif]-->
19 <![endif]-->
20 <style>body { background:#eeeeee; }</style>
20 <style>body { background:#eeeeee; }</style>
21
21
22 <script type="text/javascript" src="${h.url('/js/scripts.js')}"></script>
22 <script type="text/javascript" src="${h.asset('js/scripts.js')}"></script>
23 </head>
23 </head>
24 <body>
24 <body>
25 <%include file="/base/flash_msg.html"/>
25 <%include file="/base/flash_msg.html"/>
26
26
27 <div class="wrapper error_page">
27 <div class="wrapper error_page">
28 <div class="sidebar">
28 <div class="sidebar">
29 <a href="${h.url('home')}"><img class="error-page-logo" src="${h.url('/images/RhodeCode_Logo_Black.png')}" alt="RhodeCode"/></a>
29 <a href="${h.url('home')}"><img class="error-page-logo" src="${h.asset('images/RhodeCode_Logo_Black.png')}" alt="RhodeCode"/></a>
30 </div>
30 </div>
31 <div class="main-content">
31 <div class="main-content">
32 <h1>
32 <h1>
33 <span class="error-branding">
33 <span class="error-branding">
34 ${h.branding(c.rhodecode_name)}
34 ${h.branding(c.rhodecode_name)}
35 </span><br/>
35 </span><br/>
36 ${c.error_message} | <span class="error_message">${c.error_explanation}</span>
36 ${c.error_message} | <span class="error_message">${c.error_explanation}</span>
37 </h1>
37 </h1>
38 %if c.redirect_time:
38 %if c.redirect_time:
39 <p>${_('You will be redirected to %s in %s seconds') % (c.redirect_module,c.redirect_time)}</p>
39 <p>${_('You will be redirected to %s in %s seconds') % (c.redirect_module,c.redirect_time)}</p>
40 %endif
40 %endif
41 <div class="inner-column">
41 <div class="inner-column">
42 <h4>Possible Cause</h4>
42 <h4>Possible Cause</h4>
43 <ul>
43 <ul>
44 <li>The resource may have been deleted.</li>
44 <li>The resource may have been deleted.</li>
45 <li>You may not have access to this repository.</li>
45 <li>You may not have access to this repository.</li>
46 <li>The link may be incorrect.</li>
46 <li>The link may be incorrect.</li>
47 </ul>
47 </ul>
48 </div>
48 </div>
49 <div class="inner-column">
49 <div class="inner-column">
50 <h4>Support</h4>
50 <h4>Support</h4>
51 <p>For support, go to <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>.
51 <p>For support, go to <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>.
52 It may be useful to include your log file; see the log file locations <a href="${h.url('enterprise_log_file_locations')}">here</a>.
52 It may be useful to include your log file; see the log file locations <a href="${h.url('enterprise_log_file_locations')}">here</a>.
53 </p>
53 </p>
54 </div>
54 </div>
55 <div class="inner-column">
55 <div class="inner-column">
56 <h4>Documentation</h4>
56 <h4>Documentation</h4>
57 <p>For more information, see <a href="${h.url('enterprise_docs')}">docs.rhodecode.com</a>.</p>
57 <p>For more information, see <a href="${h.url('enterprise_docs')}">docs.rhodecode.com</a>.</p>
58 </div>
58 </div>
59 </div>
59 </div>
60 </div>
60 </div>
61
61
62 </body>
62 </body>
63
63
64 </html>
64 </html>
@@ -1,225 +1,225 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
4 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
5
5
6 <%def name="js_extra()">
6 <%def name="js_extra()">
7 <script type="text/javascript" src="${h.url('/js/mergerly.js')}"></script>
7 <script type="text/javascript" src="${h.asset('js/mergerly.js')}"></script>
8 </%def>
8 </%def>
9
9
10 <%def name="css_extra()">
10 <%def name="css_extra()">
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergerly.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.asset('css/mergerly.css')}"/>
12 </%def>
12 </%def>
13
13
14 <%def name="title()">
14 <%def name="title()">
15 ${_('%s File side-by-side diff') % c.repo_name}
15 ${_('%s File side-by-side diff') % c.repo_name}
16 %if c.rhodecode_name:
16 %if c.rhodecode_name:
17 &middot; ${h.branding(c.rhodecode_name)}
17 &middot; ${h.branding(c.rhodecode_name)}
18 %endif
18 %endif
19 </%def>
19 </%def>
20
20
21 <%def name="breadcrumbs_links()">
21 <%def name="breadcrumbs_links()">
22 r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
22 r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
23 </%def>
23 </%def>
24
24
25 <%def name="menu_bar_nav()">
25 <%def name="menu_bar_nav()">
26 ${self.menu_items(active='repositories')}
26 ${self.menu_items(active='repositories')}
27 </%def>
27 </%def>
28
28
29 <%def name="menu_bar_subnav()">
29 <%def name="menu_bar_subnav()">
30 ${self.repo_menu(active='changelog')}
30 ${self.repo_menu(active='changelog')}
31 </%def>
31 </%def>
32
32
33 <%def name="main()">
33 <%def name="main()">
34 <div class="box">
34 <div class="box">
35 <div class="title">
35 <div class="title">
36 ${self.repo_page_title(c.rhodecode_db_repo)}
36 ${self.repo_page_title(c.rhodecode_db_repo)}
37 </div>
37 </div>
38
38
39 <div class="breadcrumbs">
39 <div class="breadcrumbs">
40 ${_('Side-by-side Diff')} r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
40 ${_('Side-by-side Diff')} r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
41 </div>
41 </div>
42 <div class="cs_files">
42 <div class="cs_files">
43 <table class="compare_view_files commit_diff">
43 <table class="compare_view_files commit_diff">
44 <tr class="cs_${c.diff_data['operation']} collapse_file" fid="${c.FID}">
44 <tr class="cs_${c.diff_data['operation']} collapse_file" fid="${c.FID}">
45 <td class="cs_icon_td">
45 <td class="cs_icon_td">
46 <span class="collapse_file_icon" fid="${c.FID}"></span>
46 <span class="collapse_file_icon" fid="${c.FID}"></span>
47 </td>
47 </td>
48 <td class="cs_icon_td">
48 <td class="cs_icon_td">
49 <div class="flag_status not_reviewed hidden"></div>
49 <div class="flag_status not_reviewed hidden"></div>
50 </td>
50 </td>
51 <td class="cs_${c.diff_data['operation']}" id="a_${c.FID}">
51 <td class="cs_${c.diff_data['operation']}" id="a_${c.FID}">
52 <div class="node">
52 <div class="node">
53 <a href="#a_${c.FID}">
53 <a href="#a_${c.FID}">
54 <i class="icon-file-${c.diff_data['operation'].lower()}"></i>
54 <i class="icon-file-${c.diff_data['operation'].lower()}"></i>
55 ${h.safe_unicode(c.node1.path)}
55 ${h.safe_unicode(c.node1.path)}
56 </a>
56 </a>
57 </div>
57 </div>
58 </td>
58 </td>
59 <td>
59 <td>
60 <div class="changes pull-right">${h.fancy_file_stats(c.diff_data['stats'])}</div>
60 <div class="changes pull-right">${h.fancy_file_stats(c.diff_data['stats'])}</div>
61 <div class="comment-bubble pull-right" data-path="${h.safe_unicode(c.node1.path)}">
61 <div class="comment-bubble pull-right" data-path="${h.safe_unicode(c.node1.path)}">
62 <i class="icon-comment"></i>
62 <i class="icon-comment"></i>
63 </div>
63 </div>
64 </td>
64 </td>
65 </tr>
65 </tr>
66 <tr fid="${c.FID}" id="diff_${c.FID}" class="diff_links">
66 <tr fid="${c.FID}" id="diff_${c.FID}" class="diff_links">
67 <td></td>
67 <td></td>
68 <td></td>
68 <td></td>
69 <td class="cs_${c.diff_data['operation']}">
69 <td class="cs_${c.diff_data['operation']}">
70 ${diff_block.diff_menu(c.repo_name, h.safe_unicode(c.node1.path), c.commit_1.raw_id, c.commit_2.raw_id, c.diff_data['operation'])}
70 ${diff_block.diff_menu(c.repo_name, h.safe_unicode(c.node1.path), c.commit_1.raw_id, c.commit_2.raw_id, c.diff_data['operation'])}
71 </td>
71 </td>
72 <td class="td-actions rc-form">
72 <td class="td-actions rc-form">
73 <div id="ignorews" class="btn-link show-inline-comments">
73 <div id="ignorews" class="btn-link show-inline-comments">
74 <span data-enabled=false class="toggle">${_('Ignore whitespace')}</span>
74 <span data-enabled=false class="toggle">${_('Ignore whitespace')}</span>
75 <span data-enabled=true class="toggle" style="display: none">${_('Show whitespace')}</span>
75 <span data-enabled=true class="toggle" style="display: none">${_('Show whitespace')}</span>
76 </div> |
76 </div> |
77
77
78 <div id="edit_mode" class="btn-link show-inline-comments">
78 <div id="edit_mode" class="btn-link show-inline-comments">
79 <span data-enabled=true class="toggle">${_('Enable editor mode')}</span>
79 <span data-enabled=true class="toggle">${_('Enable editor mode')}</span>
80 <span data-enabled=false class="toggle" style="display: none">${_('Disable editor mode')}</span>
80 <span data-enabled=false class="toggle" style="display: none">${_('Disable editor mode')}</span>
81 </div> |
81 </div> |
82
82
83 <div class="btn-link show-inline-comments">
83 <div class="btn-link show-inline-comments">
84 <span id="prev_change" title="${_('Previous change')}"><i class="icon-left"></i></span>
84 <span id="prev_change" title="${_('Previous change')}"><i class="icon-left"></i></span>
85 <span id="next_change" title="${_('Next change')}"><i class="icon-right"></i></span>
85 <span id="next_change" title="${_('Next change')}"><i class="icon-right"></i></span>
86 </div>
86 </div>
87
87
88 </td>
88 </td>
89 </tr>
89 </tr>
90 <tr id="tr_${c.FID}">
90 <tr id="tr_${c.FID}">
91 <td></td>
91 <td></td>
92 <td></td>
92 <td></td>
93 <td class="injected_diff" colspan="2">
93 <td class="injected_diff" colspan="2">
94 <div class="diff-container" id="${'diff-container-%s' % (id(c.diff_data['operation']))}">
94 <div class="diff-container" id="${'diff-container-%s' % (id(c.diff_data['operation']))}">
95 <div id="${c.FID}" class="diffblock margined comm">
95 <div id="${c.FID}" class="diffblock margined comm">
96 <div class="diff-container" >
96 <div class="diff-container" >
97 <div class="diffblock comm sidebyside">
97 <div class="diffblock comm sidebyside">
98 <div class="code-header">
98 <div class="code-header">
99 <div class="changeset_header">
99 <div class="changeset_header">
100 ${_('mode')}: <span id="selected_mode">plain</span> |
100 ${_('mode')}: <span id="selected_mode">plain</span> |
101 </div>
101 </div>
102 </div>
102 </div>
103 <div id="compare"></div>
103 <div id="compare"></div>
104 </div>
104 </div>
105 </div>
105 </div>
106 </div>
106 </div>
107 </div>
107 </div>
108 </td>
108 </td>
109 </tr>
109 </tr>
110 </table>
110 </table>
111 </div>
111 </div>
112
112
113
113
114 <script>
114 <script>
115 var orig1_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),revision=c.commit_1.raw_id)}';
115 var orig1_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),revision=c.commit_1.raw_id)}';
116 var orig2_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node2.path),revision=c.commit_2.raw_id)}';
116 var orig2_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node2.path),revision=c.commit_2.raw_id)}';
117 $(document).ready(function () {
117 $(document).ready(function () {
118
118
119
119
120 var editor = $('#compare');
120 var editor = $('#compare');
121 editor.mergely({
121 editor.mergely({
122 autoupdate: true,
122 autoupdate: true,
123 width: 'auto',
123 width: 'auto',
124 height: '600',
124 height: '600',
125 fgcolor: {a: '#ddffdd', c: '#cccccc', d: '#ffdddd'},
125 fgcolor: {a: '#ddffdd', c: '#cccccc', d: '#ffdddd'},
126 bgcolor: '#fff',
126 bgcolor: '#fff',
127 viewport: false,
127 viewport: false,
128 cmsettings: {
128 cmsettings: {
129 mode: 'text/plain',
129 mode: 'text/plain',
130 readOnly: true,
130 readOnly: true,
131 lineWrapping: false,
131 lineWrapping: false,
132 lineNumbers: true
132 lineNumbers: true
133 }
133 }
134 });
134 });
135
135
136
136
137 var lhs = function(deferred) {
137 var lhs = function(deferred) {
138 if ("${c.node1.is_binary}" == "True") {
138 if ("${c.node1.is_binary}" == "True") {
139 deferred.resolve('Binary file');
139 deferred.resolve('Binary file');
140 }
140 }
141 else if ("${c.node1.commit.__class__.__name__}" == "EmptyCommit") {
141 else if ("${c.node1.commit.__class__.__name__}" == "EmptyCommit") {
142 deferred.resolve('');
142 deferred.resolve('');
143 }
143 }
144 else {
144 else {
145 editor.mergely('lhs', 'loading diff...');
145 editor.mergely('lhs', 'loading diff...');
146 $.ajax(orig1_url, {
146 $.ajax(orig1_url, {
147 dataType: 'text',
147 dataType: 'text',
148 success: function(data) {
148 success: function(data) {
149 // call the complete function to let CodeMirror know
149 // call the complete function to let CodeMirror know
150 deferred.resolve(data);
150 deferred.resolve(data);
151 }
151 }
152 });
152 });
153 }
153 }
154 };
154 };
155
155
156 var rhs = function(deferred) {
156 var rhs = function(deferred) {
157 if ("${c.node2.is_binary}" == "True") {
157 if ("${c.node2.is_binary}" == "True") {
158 deferred.resolve('Binary file');
158 deferred.resolve('Binary file');
159 }
159 }
160 else if ("${c.node2.commit.__class__.__name__}" == "EmptyCommit") {
160 else if ("${c.node2.commit.__class__.__name__}" == "EmptyCommit") {
161 deferred.resolve('');
161 deferred.resolve('');
162 }
162 }
163 else {
163 else {
164 editor.mergely('rhs', 'loading diff...');
164 editor.mergely('rhs', 'loading diff...');
165 $.ajax(orig2_url, {
165 $.ajax(orig2_url, {
166 dataType: 'text',
166 dataType: 'text',
167 success: function(data) {
167 success: function(data) {
168 // call the complete function to let CodeMirror know
168 // call the complete function to let CodeMirror know
169 deferred.resolve(data);
169 deferred.resolve(data);
170 }
170 }
171 });
171 });
172 }
172 }
173 };
173 };
174
174
175 var deferred_lhs = $.Deferred();
175 var deferred_lhs = $.Deferred();
176 var deferred_rhs = $.Deferred();
176 var deferred_rhs = $.Deferred();
177 $.when(
177 $.when(
178 deferred_lhs, deferred_rhs
178 deferred_lhs, deferred_rhs
179 ).done(function(lhs_response, rhs_response) {
179 ).done(function(lhs_response, rhs_response) {
180 editor.mergely('lhs', lhs_response);
180 editor.mergely('lhs', lhs_response);
181 editor.mergely('rhs', rhs_response);
181 editor.mergely('rhs', rhs_response);
182
182
183 var detected_mode = detectCodeMirrorModeFromExt(
183 var detected_mode = detectCodeMirrorModeFromExt(
184 '${h.safe_unicode(c.node1.path.split("/")[-1])}', true);
184 '${h.safe_unicode(c.node1.path.split("/")[-1])}', true);
185 if (detected_mode) {
185 if (detected_mode) {
186 setCodeMirrorMode(editor.mergely('cm', 'lhs'), detected_mode);
186 setCodeMirrorMode(editor.mergely('cm', 'lhs'), detected_mode);
187 setCodeMirrorMode(editor.mergely('cm', 'rhs'), detected_mode);
187 setCodeMirrorMode(editor.mergely('cm', 'rhs'), detected_mode);
188 $('#selected_mode').html(detected_mode);
188 $('#selected_mode').html(detected_mode);
189 }
189 }
190 });
190 });
191 // load via ajax, and use deferred signals to notify when finished.
191 // load via ajax, and use deferred signals to notify when finished.
192 lhs(deferred_lhs);
192 lhs(deferred_lhs);
193 rhs(deferred_rhs);
193 rhs(deferred_rhs);
194
194
195 $("#ignorews").click(function() {
195 $("#ignorews").click(function() {
196 $("#ignorews .toggle").toggle();
196 $("#ignorews .toggle").toggle();
197 var val = $('#ignorews .toggle:visible').data()['enabled'];
197 var val = $('#ignorews .toggle:visible').data()['enabled'];
198 editor.mergely('options', {ignorews: val});
198 editor.mergely('options', {ignorews: val});
199 editor.mergely('update');
199 editor.mergely('update');
200 });
200 });
201
201
202 $("#edit_mode").click(function() {
202 $("#edit_mode").click(function() {
203 $("#edit_mode .toggle").toggle();
203 $("#edit_mode .toggle").toggle();
204 var val = $('#edit_mode .toggle:visible').data()['enabled'];
204 var val = $('#edit_mode .toggle:visible').data()['enabled'];
205 editor.mergely('cm', 'lhs').setOption('readOnly', val);
205 editor.mergely('cm', 'lhs').setOption('readOnly', val);
206 editor.mergely('cm', 'rhs').setOption('readOnly', val);
206 editor.mergely('cm', 'rhs').setOption('readOnly', val);
207 editor.mergely('update');
207 editor.mergely('update');
208 });
208 });
209
209
210 $('#prev_change').on('click', function() {
210 $('#prev_change').on('click', function() {
211 editor.mergely('scrollToDiff', 'prev');
211 editor.mergely('scrollToDiff', 'prev');
212 });
212 });
213 $('#next_change').on('click', function() {
213 $('#next_change').on('click', function() {
214 editor.mergely('scrollToDiff', 'next');
214 editor.mergely('scrollToDiff', 'next');
215 });
215 });
216
216
217 // extend content dynamically on this component for readability
217 // extend content dynamically on this component for readability
218 $('#content').css({'max-width': '2000px'});
218 $('#content').css({'max-width': '2000px'});
219 editor.mergely('resize');
219 editor.mergely('resize');
220
220
221 });
221 });
222 </script>
222 </script>
223
223
224 </div>
224 </div>
225 </%def>
225 </%def>
@@ -1,77 +1,77 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.html"/>
2 <%inherit file="base/root.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Sign In')}
5 ${_('Sign In')}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <style>body{background-color:#eeeeee;}</style>
11 <style>body{background-color:#eeeeee;}</style>
12 <div class="loginbox">
12 <div class="loginbox">
13 <div class="header">
13 <div class="header">
14 <div id="header-inner" class="title">
14 <div id="header-inner" class="title">
15 <div id="logo">
15 <div id="logo">
16 <div class="logo-wrapper">
16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 </div>
18 </div>
19 %if c.rhodecode_name:
19 %if c.rhodecode_name:
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 %endif
21 %endif
22 </div>
22 </div>
23 </div>
23 </div>
24 </div>
24 </div>
25
25
26 <div class="loginwrapper">
26 <div class="loginwrapper">
27 <div class="left-column">
27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 </div>
29 </div>
30 <%block name="above_login_button" />
30 <%block name="above_login_button" />
31 <div id="login" class="right-column">
31 <div id="login" class="right-column">
32 <%include file="/base/flash_msg.html"/>
32 <%include file="/base/flash_msg.html"/>
33 <!-- login -->
33 <!-- login -->
34 <div class="sign-in-title">
34 <div class="sign-in-title">
35 <h1>${_('Sign In')}</h1>
35 <h1>${_('Sign In')}</h1>
36 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
36 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
37 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
37 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
38 %endif
38 %endif
39 </div>
39 </div>
40 <div class="inner form">
40 <div class="inner form">
41 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
41 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
42
42
43 <label for="username">${_('Username')}:</label>
43 <label for="username">${_('Username')}:</label>
44 ${h.text('username', class_='focus', value=defaults.get('username'))}
44 ${h.text('username', class_='focus', value=defaults.get('username'))}
45 %if 'username' in errors:
45 %if 'username' in errors:
46 <span class="error-message">${errors.get('username')}</span>
46 <span class="error-message">${errors.get('username')}</span>
47 <br />
47 <br />
48 %endif
48 %endif
49
49
50 <label for="password">${_('Password')}:</label>
50 <label for="password">${_('Password')}:</label>
51 ${h.password('password', class_='focus')}
51 ${h.password('password', class_='focus')}
52 %if 'password' in errors:
52 %if 'password' in errors:
53 <span class="error-message">${errors.get('password')}</span>
53 <span class="error-message">${errors.get('password')}</span>
54 <br />
54 <br />
55 %endif
55 %endif
56
56
57 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
57 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
58 <label class="checkbox" for="remember">${_('Remember me')}</label>
58 <label class="checkbox" for="remember">${_('Remember me')}</label>
59
59
60 <p class="links">
60 <p class="links">
61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'))}
61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'))}
62 </p>
62 </p>
63
63
64 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
64 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
65
65
66 ${h.end_form()}
66 ${h.end_form()}
67 <script type="text/javascript">
67 <script type="text/javascript">
68 $(document).ready(function(){
68 $(document).ready(function(){
69 $('#username').focus();
69 $('#username').focus();
70 })
70 })
71 </script>
71 </script>
72 </div>
72 </div>
73 <!-- end login -->
73 <!-- end login -->
74 <%block name="below_login_button" />
74 <%block name="below_login_button" />
75 </div>
75 </div>
76 </div>
76 </div>
77 </div>
77 </div>
@@ -1,78 +1,78 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.html"/>
2 <%inherit file="base/root.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Create an Account')}
5 ${_('Create an Account')}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10 <style>body{background-color:#eeeeee;}</style>
10 <style>body{background-color:#eeeeee;}</style>
11
11
12 <div class="loginbox">
12 <div class="loginbox">
13 <div class="header">
13 <div class="header">
14 <div id="header-inner" class="title">
14 <div id="header-inner" class="title">
15 <div id="logo">
15 <div id="logo">
16 <div class="logo-wrapper">
16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 </div>
18 </div>
19 %if c.rhodecode_name:
19 %if c.rhodecode_name:
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 %endif
21 %endif
22 </div>
22 </div>
23 </div>
23 </div>
24 </div>
24 </div>
25
25
26 <div class="loginwrapper">
26 <div class="loginwrapper">
27 <div class="left-column">
27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 </div>
29 </div>
30
30
31 <div id="register" class="right-column">
31 <div id="register" class="right-column">
32 <%include file="/base/flash_msg.html"/>
32 <%include file="/base/flash_msg.html"/>
33 <!-- login -->
33 <!-- login -->
34 <div class="sign-in-title">
34 <div class="sign-in-title">
35 <h1>${_('Reset your Password')}</h1>
35 <h1>${_('Reset your Password')}</h1>
36 <h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
36 <h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
37 </div>
37 </div>
38 <div class="inner form">
38 <div class="inner form">
39 ${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
39 ${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
40 <label for="email">${_('Email Address')}:</label>
40 <label for="email">${_('Email Address')}:</label>
41 ${h.text('email', defaults.get('email'))}
41 ${h.text('email', defaults.get('email'))}
42 %if 'email' in errors:
42 %if 'email' in errors:
43 <span class="error-message">${errors.get('email')}</span>
43 <span class="error-message">${errors.get('email')}</span>
44 <br />
44 <br />
45 %endif
45 %endif
46
46
47 %if captcha_active:
47 %if captcha_active:
48 <div class="login-captcha"
48 <div class="login-captcha"
49 <label for="email">${_('Captcha')}:</label>
49 <label for="email">${_('Captcha')}:</label>
50 ${h.hidden('recaptcha_field')}
50 ${h.hidden('recaptcha_field')}
51 <div id="recaptcha"></div>
51 <div id="recaptcha"></div>
52 %if 'recaptcha_field' in errors:
52 %if 'recaptcha_field' in errors:
53 <span class="error-message">${errors.get('recaptcha_field')}</span>
53 <span class="error-message">${errors.get('recaptcha_field')}</span>
54 <br />
54 <br />
55 %endif
55 %endif
56 </div>
56 </div>
57 %endif
57 %endif
58
58
59 ${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
59 ${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
60 <div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
60 <div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
61
61
62 ${h.end_form()}
62 ${h.end_form()}
63 </div>
63 </div>
64 </div>
64 </div>
65 </div>
65 </div>
66 </div>
66 </div>
67
67
68 %if captcha_active:
68 %if captcha_active:
69 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
69 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
70 %endif
70 %endif
71 <script type="text/javascript">
71 <script type="text/javascript">
72 $(document).ready(function(){
72 $(document).ready(function(){
73 $('#email').focus();
73 $('#email').focus();
74 %if captcha_active:
74 %if captcha_active:
75 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
75 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
76 %endif
76 %endif
77 });
77 });
78 </script>
78 </script>
@@ -1,123 +1,123 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.html"/>
2 <%inherit file="base/root.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Create an Account')}
5 ${_('Create an Account')}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10 <style>body{background-color:#eeeeee;}</style>
10 <style>body{background-color:#eeeeee;}</style>
11
11
12 <div class="loginbox">
12 <div class="loginbox">
13 <div class="header">
13 <div class="header">
14 <div id="header-inner" class="title">
14 <div id="header-inner" class="title">
15 <div id="logo">
15 <div id="logo">
16 <div class="logo-wrapper">
16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 </div>
18 </div>
19 %if c.rhodecode_name:
19 %if c.rhodecode_name:
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 %endif
21 %endif
22 </div>
22 </div>
23 </div>
23 </div>
24 </div>
24 </div>
25
25
26 <div class="loginwrapper">
26 <div class="loginwrapper">
27 <div class="left-column">
27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 </div>
29 </div>
30 <%block name="above_register_button" />
30 <%block name="above_register_button" />
31 <div id="register" class="right-column">
31 <div id="register" class="right-column">
32 <%include file="/base/flash_msg.html"/>
32 <%include file="/base/flash_msg.html"/>
33 <!-- login -->
33 <!-- login -->
34 <div class="sign-in-title">
34 <div class="sign-in-title">
35 <h1>${_('Create an account')}</h1>
35 <h1>${_('Create an account')}</h1>
36 <h4>${h.link_to(_("Go to the login page to sign in with an existing account."), request.route_path('login'))}</h4>
36 <h4>${h.link_to(_("Go to the login page to sign in with an existing account."), request.route_path('login'))}</h4>
37 </div>
37 </div>
38 <div class="inner form">
38 <div class="inner form">
39 ${h.form(request.route_path('register'), needs_csrf_token=False)}
39 ${h.form(request.route_path('register'), needs_csrf_token=False)}
40
40
41 <label for="username">${_('Username')}:</label>
41 <label for="username">${_('Username')}:</label>
42 ${h.text('username', defaults.get('username'))}
42 ${h.text('username', defaults.get('username'))}
43 %if 'username' in errors:
43 %if 'username' in errors:
44 <span class="error-message">${errors.get('username')}</span>
44 <span class="error-message">${errors.get('username')}</span>
45 <br />
45 <br />
46 %endif
46 %endif
47
47
48 <label for="password">${_('Password')}:</label>
48 <label for="password">${_('Password')}:</label>
49 ${h.password('password', defaults.get('password'))}
49 ${h.password('password', defaults.get('password'))}
50 %if 'password' in errors:
50 %if 'password' in errors:
51 <span class="error-message">${errors.get('password')}</span>
51 <span class="error-message">${errors.get('password')}</span>
52 <br />
52 <br />
53 %endif
53 %endif
54
54
55 <label for="password_confirmation">${_('Re-enter password')}:</label>
55 <label for="password_confirmation">${_('Re-enter password')}:</label>
56 ${h.password('password_confirmation', defaults.get('password_confirmation'))}
56 ${h.password('password_confirmation', defaults.get('password_confirmation'))}
57 %if 'password_confirmation' in errors:
57 %if 'password_confirmation' in errors:
58 <span class="error-message">${errors.get('password_confirmation')}</span>
58 <span class="error-message">${errors.get('password_confirmation')}</span>
59 <br />
59 <br />
60 %endif
60 %endif
61
61
62 <label for="firstname">${_('First Name')}:</label>
62 <label for="firstname">${_('First Name')}:</label>
63 ${h.text('firstname', defaults.get('firstname'))}
63 ${h.text('firstname', defaults.get('firstname'))}
64 %if 'firstname' in errors:
64 %if 'firstname' in errors:
65 <span class="error-message">${errors.get('firstname')}</span>
65 <span class="error-message">${errors.get('firstname')}</span>
66 <br />
66 <br />
67 %endif
67 %endif
68
68
69 <label for="lastname">${_('Last Name')}:</label>
69 <label for="lastname">${_('Last Name')}:</label>
70 ${h.text('lastname', defaults.get('lastname'))}
70 ${h.text('lastname', defaults.get('lastname'))}
71 %if 'lastname' in errors:
71 %if 'lastname' in errors:
72 <span class="error-message">${errors.get('lastname')}</span>
72 <span class="error-message">${errors.get('lastname')}</span>
73 <br />
73 <br />
74 %endif
74 %endif
75
75
76 <label for="email">${_('Email')}:</label>
76 <label for="email">${_('Email')}:</label>
77 ${h.text('email', defaults.get('email'))}
77 ${h.text('email', defaults.get('email'))}
78 %if 'email' in errors:
78 %if 'email' in errors:
79 <span class="error-message">${errors.get('email')}</span>
79 <span class="error-message">${errors.get('email')}</span>
80 <br />
80 <br />
81 %endif
81 %endif
82
82
83 %if captcha_active:
83 %if captcha_active:
84 <div>
84 <div>
85 <label for="recaptcha">${_('Captcha')}:</label>
85 <label for="recaptcha">${_('Captcha')}:</label>
86 ${h.hidden('recaptcha_field')}
86 ${h.hidden('recaptcha_field')}
87 <div id="recaptcha"></div>
87 <div id="recaptcha"></div>
88 %if 'recaptcha_field' in errors:
88 %if 'recaptcha_field' in errors:
89 <span class="error-message">${errors.get('recaptcha_field')}</span>
89 <span class="error-message">${errors.get('recaptcha_field')}</span>
90 <br />
90 <br />
91 %endif
91 %endif
92 </div>
92 </div>
93 %endif
93 %endif
94
94
95 %if not auto_active:
95 %if not auto_active:
96 <p class="activation_msg">
96 <p class="activation_msg">
97 ${_('Account activation requires admin approval.')}
97 ${_('Account activation requires admin approval.')}
98 </p>
98 </p>
99 %endif
99 %endif
100 <p class="register_message">
100 <p class="register_message">
101 ${register_message|n}
101 ${register_message|n}
102 </p>
102 </p>
103
103
104 ${h.submit('sign_up',_('Create Account'),class_="btn sign-in")}
104 ${h.submit('sign_up',_('Create Account'),class_="btn sign-in")}
105
105
106 ${h.end_form()}
106 ${h.end_form()}
107 </div>
107 </div>
108 <%block name="below_register_button" />
108 <%block name="below_register_button" />
109 </div>
109 </div>
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 %if captcha_active:
113 %if captcha_active:
114 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
114 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
115 %endif
115 %endif
116 <script type="text/javascript">
116 <script type="text/javascript">
117 $(document).ready(function(){
117 $(document).ready(function(){
118 $('#username').focus();
118 $('#username').focus();
119 %if captcha_active:
119 %if captcha_active:
120 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
120 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
121 %endif
121 %endif
122 });
122 });
123 </script>
123 </script>
General Comments 0
You need to be logged in to leave comments. Login now