##// END OF EJS Templates
config: rename options to show_revision_number and show_sha_length...
Mads Kiilerich -
r3651:659bd922 beta
parent child Browse files
Show More
@@ -1,481 +1,481 b''
1 1 ################################################################################
2 2 ################################################################################
3 3 # RhodeCode - Pylons environment configuration #
4 4 # #
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10 pdebug = false
11 11 ################################################################################
12 12 ## Uncomment and replace with the address which should receive ##
13 13 ## any error reports after application crash ##
14 14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 15 ################################################################################
16 16 #email_to = admin@localhost
17 17 #error_email_from = paste_error@localhost
18 18 #app_email_from = rhodecode-noreply@localhost
19 19 #error_message =
20 20 #email_prefix = [RhodeCode]
21 21
22 22 #smtp_server = mail.server.com
23 23 #smtp_username =
24 24 #smtp_password =
25 25 #smtp_port =
26 26 #smtp_use_tls = false
27 27 #smtp_use_ssl = true
28 28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 29 #smtp_auth =
30 30
31 31 [server:main]
32 32 ## PASTE
33 33 ## nr of threads to spawn
34 34 #threadpool_workers = 5
35 35
36 36 ## max request before thread respawn
37 37 #threadpool_max_requests = 10
38 38
39 39 ## option to use threads of process
40 40 #use_threadpool = true
41 41
42 42 #use = egg:Paste#http
43 43
44 44 ## WAITRESS
45 45 threads = 5
46 46 ## 100GB
47 47 max_request_body_size = 107374182400
48 48 use = egg:waitress#main
49 49
50 50 host = 0.0.0.0
51 51 port = 5000
52 52
53 53 ## prefix middleware for rc
54 54 #[filter:proxy-prefix]
55 55 #use = egg:PasteDeploy#prefix
56 56 #prefix = /<your-prefix>
57 57
58 58 [app:main]
59 59 use = egg:rhodecode
60 60 ## enable proxy prefix middleware
61 61 #filter-with = proxy-prefix
62 62
63 63 full_stack = true
64 64 static_files = true
65 65 ## Optional Languages
66 66 ## en, fr, ja, pt_BR, zh_CN, zh_TW, pl
67 67 lang = en
68 68 cache_dir = %(here)s/data
69 69 index_dir = %(here)s/data/index
70 70
71 71 ## uncomment and set this path to use archive download cache
72 72 #archive_cache_dir = /tmp/tarballcache
73 73
74 74 ## change this to unique ID for security
75 75 app_instance_uuid = rc-production
76 76
77 77 ## cut off limit for large diffs (size in bytes)
78 78 cut_off_limit = 256000
79 79
80 80 ## use cache version of scm repo everywhere
81 81 vcs_full_cache = true
82 82
83 83 ## force https in RhodeCode, fixes https redirects, assumes it's always https
84 84 force_https = false
85 85
86 86 ## use Strict-Transport-Security headers
87 87 use_htsts = false
88 88
89 89 ## number of commits stats will parse on each iteration
90 90 commit_parse_limit = 25
91 91
92 92 ## number of items displayed in lightweight dashboard before paginating is shown
93 93 dashboard_items = 100
94 94
95 95 ## use gravatar service to display avatars
96 96 use_gravatar = true
97 97
98 98 ## path to git executable
99 99 git_path = git
100 100
101 101 ## git rev filter option, --all is the default filter, if you need to
102 102 ## hide all refs in changelog switch this to --branches --tags
103 103 git_rev_filter=--all
104 104
105 105 ## RSS feed options
106 106 rss_cut_off_limit = 256000
107 107 rss_items_per_page = 10
108 108 rss_include_diff = false
109 109
110 ## show hash options for changelog
111 sha_len = 12
112 sha_show_numeric_rev = true
110 ## options for showing and identifying changesets
111 show_sha_length = 12
112 show_revision_number = true
113 113
114 114
115 115 ## alternative_gravatar_url allows you to use your own avatar server application
116 116 ## the following parts of the URL will be replaced
117 117 ## {email} user email
118 118 ## {md5email} md5 hash of the user email (like at gravatar.com)
119 119 ## {size} size of the image that is expected from the server application
120 120 ## {scheme} http/https from RhodeCode server
121 121 ## {netloc} network location from RhodeCode server
122 122 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
123 123 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
124 124
125 125
126 126 ## container auth options
127 127 container_auth_enabled = false
128 128 proxypass_auth_enabled = false
129 129
130 130 ## default encoding used to convert from and to unicode
131 131 ## can be also a comma seperated list of encoding in case of mixed encodings
132 132 default_encoding = utf8
133 133
134 134 ## overwrite schema of clone url
135 135 ## available vars:
136 136 ## scheme - http/https
137 137 ## user - current user
138 138 ## pass - password
139 139 ## netloc - network location
140 140 ## path - usually repo_name
141 141
142 142 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
143 143
144 144 ## issue tracking mapping for commits messages
145 145 ## comment out issue_pat, issue_server, issue_prefix to enable
146 146
147 147 ## pattern to get the issues from commit messages
148 148 ## default one used here is #<numbers> with a regex passive group for `#`
149 149 ## {id} will be all groups matched from this pattern
150 150
151 151 issue_pat = (?:\s*#)(\d+)
152 152
153 153 ## server url to the issue, each {id} will be replaced with match
154 154 ## fetched from the regex and {repo} is replaced with full repository name
155 155 ## including groups {repo_name} is replaced with just name of repo
156 156
157 157 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
158 158
159 159 ## prefix to add to link to indicate it's an url
160 160 ## #314 will be replaced by <issue_prefix><id>
161 161
162 162 issue_prefix = #
163 163
164 164 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
165 165 ## multiple patterns, to other issues server, wiki or others
166 166 ## below an example how to create a wiki pattern
167 167 # #wiki-some-id -> https://mywiki.com/some-id
168 168
169 169 #issue_pat_wiki = (?:wiki-)(.+)
170 170 #issue_server_link_wiki = https://mywiki.com/{id}
171 171 #issue_prefix_wiki = WIKI-
172 172
173 173
174 174 ## instance-id prefix
175 175 ## a prefix key for this instance used for cache invalidation when running
176 176 ## multiple instances of rhodecode, make sure it's globally unique for
177 177 ## all running rhodecode instances. Leave empty if you don't use it
178 178 instance_id =
179 179
180 180 ## alternative return HTTP header for failed authentication. Default HTTP
181 181 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
182 182 ## handling that. Set this variable to 403 to return HTTPForbidden
183 183 auth_ret_code =
184 184
185 185 ## locking return code. When repository is locked return this HTTP code. 2XX
186 186 ## codes don't break the transactions while 4XX codes do
187 187 lock_ret_code = 423
188 188
189 189
190 190 ####################################
191 191 ### CELERY CONFIG ####
192 192 ####################################
193 193 use_celery = false
194 194 broker.host = localhost
195 195 broker.vhost = rabbitmqhost
196 196 broker.port = 5672
197 197 broker.user = rabbitmq
198 198 broker.password = qweqwe
199 199
200 200 celery.imports = rhodecode.lib.celerylib.tasks
201 201
202 202 celery.result.backend = amqp
203 203 celery.result.dburi = amqp://
204 204 celery.result.serialier = json
205 205
206 206 #celery.send.task.error.emails = true
207 207 #celery.amqp.task.result.expires = 18000
208 208
209 209 celeryd.concurrency = 2
210 210 #celeryd.log.file = celeryd.log
211 211 celeryd.log.level = debug
212 212 celeryd.max.tasks.per.child = 1
213 213
214 214 ## tasks will never be sent to the queue, but executed locally instead.
215 215 celery.always.eager = false
216 216
217 217 ####################################
218 218 ### BEAKER CACHE ####
219 219 ####################################
220 220 beaker.cache.data_dir=%(here)s/data/cache/data
221 221 beaker.cache.lock_dir=%(here)s/data/cache/lock
222 222
223 223 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
224 224
225 225 beaker.cache.super_short_term.type=memory
226 226 beaker.cache.super_short_term.expire=10
227 227 beaker.cache.super_short_term.key_length = 256
228 228
229 229 beaker.cache.short_term.type=memory
230 230 beaker.cache.short_term.expire=60
231 231 beaker.cache.short_term.key_length = 256
232 232
233 233 beaker.cache.long_term.type=memory
234 234 beaker.cache.long_term.expire=36000
235 235 beaker.cache.long_term.key_length = 256
236 236
237 237 beaker.cache.sql_cache_short.type=memory
238 238 beaker.cache.sql_cache_short.expire=10
239 239 beaker.cache.sql_cache_short.key_length = 256
240 240
241 241 beaker.cache.sql_cache_med.type=memory
242 242 beaker.cache.sql_cache_med.expire=360
243 243 beaker.cache.sql_cache_med.key_length = 256
244 244
245 245 beaker.cache.sql_cache_long.type=file
246 246 beaker.cache.sql_cache_long.expire=3600
247 247 beaker.cache.sql_cache_long.key_length = 256
248 248
249 249 ####################################
250 250 ### BEAKER SESSION ####
251 251 ####################################
252 252 ## Type of storage used for the session, current types are
253 253 ## dbm, file, memcached, database, and memory.
254 254 ## The storage uses the Container API
255 255 ## that is also used by the cache system.
256 256
257 257 ## db session ##
258 258 #beaker.session.type = ext:database
259 259 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
260 260 #beaker.session.table_name = db_session
261 261
262 262 ## encrypted cookie client side session, good for many instances ##
263 263 #beaker.session.type = cookie
264 264
265 265 ## file based cookies (default) ##
266 266 #beaker.session.type = file
267 267
268 268
269 269 beaker.session.key = rhodecode
270 270 ## secure cookie requires AES python libraries
271 271 #beaker.session.encrypt_key = <key_for_encryption>
272 272 #beaker.session.validate_key = <validation_key>
273 273
274 274 ## sets session as invalid if it haven't been accessed for given amount of time
275 275 beaker.session.timeout = 2592000
276 276 beaker.session.httponly = true
277 277 #beaker.session.cookie_path = /<your-prefix>
278 278
279 279 ## uncomment for https secure cookie
280 280 beaker.session.secure = false
281 281
282 282 ## auto save the session to not to use .save()
283 283 beaker.session.auto = False
284 284
285 285 ## default cookie expiration time in seconds `true` expire at browser close ##
286 286 #beaker.session.cookie_expires = 3600
287 287
288 288
289 289 ############################
290 290 ## ERROR HANDLING SYSTEMS ##
291 291 ############################
292 292
293 293 ####################
294 294 ### [errormator] ###
295 295 ####################
296 296
297 297 ## Errormator is tailored to work with RhodeCode, see
298 298 ## http://errormator.com for details how to obtain an account
299 299 ## you must install python package `errormator_client` to make it work
300 300
301 301 ## errormator enabled
302 302 errormator = false
303 303
304 304 errormator.server_url = https://api.errormator.com
305 305 errormator.api_key = YOUR_API_KEY
306 306
307 307 ## TWEAK AMOUNT OF INFO SENT HERE
308 308
309 309 ## enables 404 error logging (default False)
310 310 errormator.report_404 = false
311 311
312 312 ## time in seconds after request is considered being slow (default 1)
313 313 errormator.slow_request_time = 1
314 314
315 315 ## record slow requests in application
316 316 ## (needs to be enabled for slow datastore recording and time tracking)
317 317 errormator.slow_requests = true
318 318
319 319 ## enable hooking to application loggers
320 320 # errormator.logging = true
321 321
322 322 ## minimum log level for log capture
323 323 # errormator.logging.level = WARNING
324 324
325 325 ## send logs only from erroneous/slow requests
326 326 ## (saves API quota for intensive logging)
327 327 errormator.logging_on_error = false
328 328
329 329 ## list of additonal keywords that should be grabbed from environ object
330 330 ## can be string with comma separated list of words in lowercase
331 331 ## (by default client will always send following info:
332 332 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
333 333 ## start with HTTP* this list be extended with additional keywords here
334 334 errormator.environ_keys_whitelist =
335 335
336 336
337 337 ## list of keywords that should be blanked from request object
338 338 ## can be string with comma separated list of words in lowercase
339 339 ## (by default client will always blank keys that contain following words
340 340 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
341 341 ## this list be extended with additional keywords set here
342 342 errormator.request_keys_blacklist =
343 343
344 344
345 345 ## list of namespaces that should be ignores when gathering log entries
346 346 ## can be string with comma separated list of namespaces
347 347 ## (by default the client ignores own entries: errormator_client.client)
348 348 errormator.log_namespace_blacklist =
349 349
350 350
351 351 ################
352 352 ### [sentry] ###
353 353 ################
354 354
355 355 ## sentry is a alternative open source error aggregator
356 356 ## you must install python packages `sentry` and `raven` to enable
357 357
358 358 sentry.dsn = YOUR_DNS
359 359 sentry.servers =
360 360 sentry.name =
361 361 sentry.key =
362 362 sentry.public_key =
363 363 sentry.secret_key =
364 364 sentry.project =
365 365 sentry.site =
366 366 sentry.include_paths =
367 367 sentry.exclude_paths =
368 368
369 369
370 370 ################################################################################
371 371 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
372 372 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
373 373 ## execute malicious code after an exception is raised. ##
374 374 ################################################################################
375 375 #set debug = false
376 376
377 377 ##################################
378 378 ### LOGVIEW CONFIG ###
379 379 ##################################
380 380 logview.sqlalchemy = #faa
381 381 logview.pylons.templating = #bfb
382 382 logview.pylons.util = #eee
383 383
384 384 #########################################################
385 385 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
386 386 #########################################################
387 387 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
388 388 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
389 389 sqlalchemy.db1.echo = false
390 390 sqlalchemy.db1.pool_recycle = 3600
391 391 sqlalchemy.db1.convert_unicode = true
392 392
393 393 ################################
394 394 ### LOGGING CONFIGURATION ####
395 395 ################################
396 396 [loggers]
397 397 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
398 398
399 399 [handlers]
400 400 keys = console, console_sql
401 401
402 402 [formatters]
403 403 keys = generic, color_formatter, color_formatter_sql
404 404
405 405 #############
406 406 ## LOGGERS ##
407 407 #############
408 408 [logger_root]
409 409 level = NOTSET
410 410 handlers = console
411 411
412 412 [logger_routes]
413 413 level = DEBUG
414 414 handlers =
415 415 qualname = routes.middleware
416 416 ## "level = DEBUG" logs the route matched and routing variables.
417 417 propagate = 1
418 418
419 419 [logger_beaker]
420 420 level = DEBUG
421 421 handlers =
422 422 qualname = beaker.container
423 423 propagate = 1
424 424
425 425 [logger_templates]
426 426 level = INFO
427 427 handlers =
428 428 qualname = pylons.templating
429 429 propagate = 1
430 430
431 431 [logger_rhodecode]
432 432 level = DEBUG
433 433 handlers =
434 434 qualname = rhodecode
435 435 propagate = 1
436 436
437 437 [logger_sqlalchemy]
438 438 level = INFO
439 439 handlers = console_sql
440 440 qualname = sqlalchemy.engine
441 441 propagate = 0
442 442
443 443 [logger_whoosh_indexer]
444 444 level = DEBUG
445 445 handlers =
446 446 qualname = whoosh_indexer
447 447 propagate = 1
448 448
449 449 ##############
450 450 ## HANDLERS ##
451 451 ##############
452 452
453 453 [handler_console]
454 454 class = StreamHandler
455 455 args = (sys.stderr,)
456 456 level = DEBUG
457 457 formatter = color_formatter
458 458
459 459 [handler_console_sql]
460 460 class = StreamHandler
461 461 args = (sys.stderr,)
462 462 level = DEBUG
463 463 formatter = color_formatter_sql
464 464
465 465 ################
466 466 ## FORMATTERS ##
467 467 ################
468 468
469 469 [formatter_generic]
470 470 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
471 471 datefmt = %Y-%m-%d %H:%M:%S
472 472
473 473 [formatter_color_formatter]
474 474 class=rhodecode.lib.colored_formatter.ColorFormatter
475 475 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
476 476 datefmt = %Y-%m-%d %H:%M:%S
477 477
478 478 [formatter_color_formatter_sql]
479 479 class=rhodecode.lib.colored_formatter.ColorFormatterSql
480 480 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
481 481 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,481 +1,481 b''
1 1 ################################################################################
2 2 ################################################################################
3 3 # RhodeCode - Pylons environment configuration #
4 4 # #
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10 pdebug = false
11 11 ################################################################################
12 12 ## Uncomment and replace with the address which should receive ##
13 13 ## any error reports after application crash ##
14 14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 15 ################################################################################
16 16 #email_to = admin@localhost
17 17 #error_email_from = paste_error@localhost
18 18 #app_email_from = rhodecode-noreply@localhost
19 19 #error_message =
20 20 #email_prefix = [RhodeCode]
21 21
22 22 #smtp_server = mail.server.com
23 23 #smtp_username =
24 24 #smtp_password =
25 25 #smtp_port =
26 26 #smtp_use_tls = false
27 27 #smtp_use_ssl = true
28 28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 29 #smtp_auth =
30 30
31 31 [server:main]
32 32 ## PASTE
33 33 ## nr of threads to spawn
34 34 #threadpool_workers = 5
35 35
36 36 ## max request before thread respawn
37 37 #threadpool_max_requests = 10
38 38
39 39 ## option to use threads of process
40 40 #use_threadpool = true
41 41
42 42 #use = egg:Paste#http
43 43
44 44 ## WAITRESS
45 45 threads = 5
46 46 ## 100GB
47 47 max_request_body_size = 107374182400
48 48 use = egg:waitress#main
49 49
50 50 host = 127.0.0.1
51 51 port = 8001
52 52
53 53 ## prefix middleware for rc
54 54 #[filter:proxy-prefix]
55 55 #use = egg:PasteDeploy#prefix
56 56 #prefix = /<your-prefix>
57 57
58 58 [app:main]
59 59 use = egg:rhodecode
60 60 ## enable proxy prefix middleware
61 61 #filter-with = proxy-prefix
62 62
63 63 full_stack = true
64 64 static_files = true
65 65 ## Optional Languages
66 66 ## en, fr, ja, pt_BR, zh_CN, zh_TW, pl
67 67 lang = en
68 68 cache_dir = %(here)s/data
69 69 index_dir = %(here)s/data/index
70 70
71 71 ## uncomment and set this path to use archive download cache
72 72 #archive_cache_dir = /tmp/tarballcache
73 73
74 74 ## change this to unique ID for security
75 75 app_instance_uuid = rc-production
76 76
77 77 ## cut off limit for large diffs (size in bytes)
78 78 cut_off_limit = 256000
79 79
80 80 ## use cache version of scm repo everywhere
81 81 vcs_full_cache = true
82 82
83 83 ## force https in RhodeCode, fixes https redirects, assumes it's always https
84 84 force_https = false
85 85
86 86 ## use Strict-Transport-Security headers
87 87 use_htsts = false
88 88
89 89 ## number of commits stats will parse on each iteration
90 90 commit_parse_limit = 25
91 91
92 92 ## number of items displayed in lightweight dashboard before paginating is shown
93 93 dashboard_items = 100
94 94
95 95 ## use gravatar service to display avatars
96 96 use_gravatar = true
97 97
98 98 ## path to git executable
99 99 git_path = git
100 100
101 101 ## git rev filter option, --all is the default filter, if you need to
102 102 ## hide all refs in changelog switch this to --branches --tags
103 103 git_rev_filter=--all
104 104
105 105 ## RSS feed options
106 106 rss_cut_off_limit = 256000
107 107 rss_items_per_page = 10
108 108 rss_include_diff = false
109 109
110 ## show hash options for changelog
111 sha_len = 12
112 sha_show_numeric_rev = true
110 ## options for showing and identifying changesets
111 show_sha_length = 12
112 show_revision_number = true
113 113
114 114
115 115 ## alternative_gravatar_url allows you to use your own avatar server application
116 116 ## the following parts of the URL will be replaced
117 117 ## {email} user email
118 118 ## {md5email} md5 hash of the user email (like at gravatar.com)
119 119 ## {size} size of the image that is expected from the server application
120 120 ## {scheme} http/https from RhodeCode server
121 121 ## {netloc} network location from RhodeCode server
122 122 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
123 123 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
124 124
125 125
126 126 ## container auth options
127 127 container_auth_enabled = false
128 128 proxypass_auth_enabled = false
129 129
130 130 ## default encoding used to convert from and to unicode
131 131 ## can be also a comma seperated list of encoding in case of mixed encodings
132 132 default_encoding = utf8
133 133
134 134 ## overwrite schema of clone url
135 135 ## available vars:
136 136 ## scheme - http/https
137 137 ## user - current user
138 138 ## pass - password
139 139 ## netloc - network location
140 140 ## path - usually repo_name
141 141
142 142 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
143 143
144 144 ## issue tracking mapping for commits messages
145 145 ## comment out issue_pat, issue_server, issue_prefix to enable
146 146
147 147 ## pattern to get the issues from commit messages
148 148 ## default one used here is #<numbers> with a regex passive group for `#`
149 149 ## {id} will be all groups matched from this pattern
150 150
151 151 issue_pat = (?:\s*#)(\d+)
152 152
153 153 ## server url to the issue, each {id} will be replaced with match
154 154 ## fetched from the regex and {repo} is replaced with full repository name
155 155 ## including groups {repo_name} is replaced with just name of repo
156 156
157 157 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
158 158
159 159 ## prefix to add to link to indicate it's an url
160 160 ## #314 will be replaced by <issue_prefix><id>
161 161
162 162 issue_prefix = #
163 163
164 164 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
165 165 ## multiple patterns, to other issues server, wiki or others
166 166 ## below an example how to create a wiki pattern
167 167 # #wiki-some-id -> https://mywiki.com/some-id
168 168
169 169 #issue_pat_wiki = (?:wiki-)(.+)
170 170 #issue_server_link_wiki = https://mywiki.com/{id}
171 171 #issue_prefix_wiki = WIKI-
172 172
173 173
174 174 ## instance-id prefix
175 175 ## a prefix key for this instance used for cache invalidation when running
176 176 ## multiple instances of rhodecode, make sure it's globally unique for
177 177 ## all running rhodecode instances. Leave empty if you don't use it
178 178 instance_id =
179 179
180 180 ## alternative return HTTP header for failed authentication. Default HTTP
181 181 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
182 182 ## handling that. Set this variable to 403 to return HTTPForbidden
183 183 auth_ret_code =
184 184
185 185 ## locking return code. When repository is locked return this HTTP code. 2XX
186 186 ## codes don't break the transactions while 4XX codes do
187 187 lock_ret_code = 423
188 188
189 189
190 190 ####################################
191 191 ### CELERY CONFIG ####
192 192 ####################################
193 193 use_celery = false
194 194 broker.host = localhost
195 195 broker.vhost = rabbitmqhost
196 196 broker.port = 5672
197 197 broker.user = rabbitmq
198 198 broker.password = qweqwe
199 199
200 200 celery.imports = rhodecode.lib.celerylib.tasks
201 201
202 202 celery.result.backend = amqp
203 203 celery.result.dburi = amqp://
204 204 celery.result.serialier = json
205 205
206 206 #celery.send.task.error.emails = true
207 207 #celery.amqp.task.result.expires = 18000
208 208
209 209 celeryd.concurrency = 2
210 210 #celeryd.log.file = celeryd.log
211 211 celeryd.log.level = debug
212 212 celeryd.max.tasks.per.child = 1
213 213
214 214 ## tasks will never be sent to the queue, but executed locally instead.
215 215 celery.always.eager = false
216 216
217 217 ####################################
218 218 ### BEAKER CACHE ####
219 219 ####################################
220 220 beaker.cache.data_dir=%(here)s/data/cache/data
221 221 beaker.cache.lock_dir=%(here)s/data/cache/lock
222 222
223 223 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
224 224
225 225 beaker.cache.super_short_term.type=memory
226 226 beaker.cache.super_short_term.expire=10
227 227 beaker.cache.super_short_term.key_length = 256
228 228
229 229 beaker.cache.short_term.type=memory
230 230 beaker.cache.short_term.expire=60
231 231 beaker.cache.short_term.key_length = 256
232 232
233 233 beaker.cache.long_term.type=memory
234 234 beaker.cache.long_term.expire=36000
235 235 beaker.cache.long_term.key_length = 256
236 236
237 237 beaker.cache.sql_cache_short.type=memory
238 238 beaker.cache.sql_cache_short.expire=10
239 239 beaker.cache.sql_cache_short.key_length = 256
240 240
241 241 beaker.cache.sql_cache_med.type=memory
242 242 beaker.cache.sql_cache_med.expire=360
243 243 beaker.cache.sql_cache_med.key_length = 256
244 244
245 245 beaker.cache.sql_cache_long.type=file
246 246 beaker.cache.sql_cache_long.expire=3600
247 247 beaker.cache.sql_cache_long.key_length = 256
248 248
249 249 ####################################
250 250 ### BEAKER SESSION ####
251 251 ####################################
252 252 ## Type of storage used for the session, current types are
253 253 ## dbm, file, memcached, database, and memory.
254 254 ## The storage uses the Container API
255 255 ## that is also used by the cache system.
256 256
257 257 ## db session ##
258 258 #beaker.session.type = ext:database
259 259 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
260 260 #beaker.session.table_name = db_session
261 261
262 262 ## encrypted cookie client side session, good for many instances ##
263 263 #beaker.session.type = cookie
264 264
265 265 ## file based cookies (default) ##
266 266 #beaker.session.type = file
267 267
268 268
269 269 beaker.session.key = rhodecode
270 270 ## secure cookie requires AES python libraries
271 271 #beaker.session.encrypt_key = <key_for_encryption>
272 272 #beaker.session.validate_key = <validation_key>
273 273
274 274 ## sets session as invalid if it haven't been accessed for given amount of time
275 275 beaker.session.timeout = 2592000
276 276 beaker.session.httponly = true
277 277 #beaker.session.cookie_path = /<your-prefix>
278 278
279 279 ## uncomment for https secure cookie
280 280 beaker.session.secure = false
281 281
282 282 ## auto save the session to not to use .save()
283 283 beaker.session.auto = False
284 284
285 285 ## default cookie expiration time in seconds `true` expire at browser close ##
286 286 #beaker.session.cookie_expires = 3600
287 287
288 288
289 289 ############################
290 290 ## ERROR HANDLING SYSTEMS ##
291 291 ############################
292 292
293 293 ####################
294 294 ### [errormator] ###
295 295 ####################
296 296
297 297 ## Errormator is tailored to work with RhodeCode, see
298 298 ## http://errormator.com for details how to obtain an account
299 299 ## you must install python package `errormator_client` to make it work
300 300
301 301 ## errormator enabled
302 302 errormator = false
303 303
304 304 errormator.server_url = https://api.errormator.com
305 305 errormator.api_key = YOUR_API_KEY
306 306
307 307 ## TWEAK AMOUNT OF INFO SENT HERE
308 308
309 309 ## enables 404 error logging (default False)
310 310 errormator.report_404 = false
311 311
312 312 ## time in seconds after request is considered being slow (default 1)
313 313 errormator.slow_request_time = 1
314 314
315 315 ## record slow requests in application
316 316 ## (needs to be enabled for slow datastore recording and time tracking)
317 317 errormator.slow_requests = true
318 318
319 319 ## enable hooking to application loggers
320 320 # errormator.logging = true
321 321
322 322 ## minimum log level for log capture
323 323 # errormator.logging.level = WARNING
324 324
325 325 ## send logs only from erroneous/slow requests
326 326 ## (saves API quota for intensive logging)
327 327 errormator.logging_on_error = false
328 328
329 329 ## list of additonal keywords that should be grabbed from environ object
330 330 ## can be string with comma separated list of words in lowercase
331 331 ## (by default client will always send following info:
332 332 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
333 333 ## start with HTTP* this list be extended with additional keywords here
334 334 errormator.environ_keys_whitelist =
335 335
336 336
337 337 ## list of keywords that should be blanked from request object
338 338 ## can be string with comma separated list of words in lowercase
339 339 ## (by default client will always blank keys that contain following words
340 340 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
341 341 ## this list be extended with additional keywords set here
342 342 errormator.request_keys_blacklist =
343 343
344 344
345 345 ## list of namespaces that should be ignores when gathering log entries
346 346 ## can be string with comma separated list of namespaces
347 347 ## (by default the client ignores own entries: errormator_client.client)
348 348 errormator.log_namespace_blacklist =
349 349
350 350
351 351 ################
352 352 ### [sentry] ###
353 353 ################
354 354
355 355 ## sentry is a alternative open source error aggregator
356 356 ## you must install python packages `sentry` and `raven` to enable
357 357
358 358 sentry.dsn = YOUR_DNS
359 359 sentry.servers =
360 360 sentry.name =
361 361 sentry.key =
362 362 sentry.public_key =
363 363 sentry.secret_key =
364 364 sentry.project =
365 365 sentry.site =
366 366 sentry.include_paths =
367 367 sentry.exclude_paths =
368 368
369 369
370 370 ################################################################################
371 371 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
372 372 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
373 373 ## execute malicious code after an exception is raised. ##
374 374 ################################################################################
375 375 set debug = false
376 376
377 377 ##################################
378 378 ### LOGVIEW CONFIG ###
379 379 ##################################
380 380 logview.sqlalchemy = #faa
381 381 logview.pylons.templating = #bfb
382 382 logview.pylons.util = #eee
383 383
384 384 #########################################################
385 385 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
386 386 #########################################################
387 387 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
388 388 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
389 389 sqlalchemy.db1.echo = false
390 390 sqlalchemy.db1.pool_recycle = 3600
391 391 sqlalchemy.db1.convert_unicode = true
392 392
393 393 ################################
394 394 ### LOGGING CONFIGURATION ####
395 395 ################################
396 396 [loggers]
397 397 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
398 398
399 399 [handlers]
400 400 keys = console, console_sql
401 401
402 402 [formatters]
403 403 keys = generic, color_formatter, color_formatter_sql
404 404
405 405 #############
406 406 ## LOGGERS ##
407 407 #############
408 408 [logger_root]
409 409 level = NOTSET
410 410 handlers = console
411 411
412 412 [logger_routes]
413 413 level = DEBUG
414 414 handlers =
415 415 qualname = routes.middleware
416 416 ## "level = DEBUG" logs the route matched and routing variables.
417 417 propagate = 1
418 418
419 419 [logger_beaker]
420 420 level = DEBUG
421 421 handlers =
422 422 qualname = beaker.container
423 423 propagate = 1
424 424
425 425 [logger_templates]
426 426 level = INFO
427 427 handlers =
428 428 qualname = pylons.templating
429 429 propagate = 1
430 430
431 431 [logger_rhodecode]
432 432 level = DEBUG
433 433 handlers =
434 434 qualname = rhodecode
435 435 propagate = 1
436 436
437 437 [logger_sqlalchemy]
438 438 level = INFO
439 439 handlers = console_sql
440 440 qualname = sqlalchemy.engine
441 441 propagate = 0
442 442
443 443 [logger_whoosh_indexer]
444 444 level = DEBUG
445 445 handlers =
446 446 qualname = whoosh_indexer
447 447 propagate = 1
448 448
449 449 ##############
450 450 ## HANDLERS ##
451 451 ##############
452 452
453 453 [handler_console]
454 454 class = StreamHandler
455 455 args = (sys.stderr,)
456 456 level = INFO
457 457 formatter = generic
458 458
459 459 [handler_console_sql]
460 460 class = StreamHandler
461 461 args = (sys.stderr,)
462 462 level = WARN
463 463 formatter = generic
464 464
465 465 ################
466 466 ## FORMATTERS ##
467 467 ################
468 468
469 469 [formatter_generic]
470 470 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
471 471 datefmt = %Y-%m-%d %H:%M:%S
472 472
473 473 [formatter_color_formatter]
474 474 class=rhodecode.lib.colored_formatter.ColorFormatter
475 475 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
476 476 datefmt = %Y-%m-%d %H:%M:%S
477 477
478 478 [formatter_color_formatter_sql]
479 479 class=rhodecode.lib.colored_formatter.ColorFormatterSql
480 480 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
481 481 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,491 +1,491 b''
1 1 ################################################################################
2 2 ################################################################################
3 3 # RhodeCode - Pylons environment configuration #
4 4 # #
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10 pdebug = false
11 11 ################################################################################
12 12 ## Uncomment and replace with the address which should receive ##
13 13 ## any error reports after application crash ##
14 14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 15 ################################################################################
16 16 #email_to = admin@localhost
17 17 #error_email_from = paste_error@localhost
18 18 #app_email_from = rhodecode-noreply@localhost
19 19 #error_message =
20 20 #email_prefix = [RhodeCode]
21 21
22 22 #smtp_server = mail.server.com
23 23 #smtp_username =
24 24 #smtp_password =
25 25 #smtp_port =
26 26 #smtp_use_tls = false
27 27 #smtp_use_ssl = true
28 28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 29 #smtp_auth =
30 30
31 31 [server:main]
32 32 ## PASTE
33 33 ## nr of threads to spawn
34 34 #threadpool_workers = 5
35 35
36 36 ## max request before thread respawn
37 37 #threadpool_max_requests = 10
38 38
39 39 ## option to use threads of process
40 40 #use_threadpool = true
41 41
42 42 #use = egg:Paste#http
43 43
44 44 ## WAITRESS
45 45 threads = 5
46 46 ## 100GB
47 47 max_request_body_size = 107374182400
48 48 use = egg:waitress#main
49 49
50 50 host = 127.0.0.1
51 51 port = 5000
52 52
53 53 ## prefix middleware for rc
54 54 #[filter:proxy-prefix]
55 55 #use = egg:PasteDeploy#prefix
56 56 #prefix = /<your-prefix>
57 57
58 58 [app:main]
59 59 use = egg:rhodecode
60 60 ## enable proxy prefix middleware
61 61 #filter-with = proxy-prefix
62 62
63 63 full_stack = true
64 64 static_files = true
65 65 ## Optional Languages
66 66 ## en, fr, ja, pt_BR, zh_CN, zh_TW, pl
67 67 lang = en
68 68 cache_dir = %(here)s/data
69 69 index_dir = %(here)s/data/index
70 70
71 71 ## uncomment and set this path to use archive download cache
72 72 #archive_cache_dir = /tmp/tarballcache
73 73
74 74 ## change this to unique ID for security
75 75 app_instance_uuid = ${app_instance_uuid}
76 76
77 77 ## cut off limit for large diffs (size in bytes)
78 78 cut_off_limit = 256000
79 79
80 80 ## use cache version of scm repo everywhere
81 81 vcs_full_cache = true
82 82
83 83 ## force https in RhodeCode, fixes https redirects, assumes it's always https
84 84 force_https = false
85 85
86 86 ## use Strict-Transport-Security headers
87 87 use_htsts = false
88 88
89 89 ## number of commits stats will parse on each iteration
90 90 commit_parse_limit = 25
91 91
92 92 ## number of items displayed in lightweight dashboard before paginating is shown
93 93 dashboard_items = 100
94 94
95 95 ## use gravatar service to display avatars
96 96 use_gravatar = true
97 97
98 98 ## path to git executable
99 99 git_path = git
100 100
101 101 ## git rev filter option, --all is the default filter, if you need to
102 102 ## hide all refs in changelog switch this to --branches --tags
103 103 git_rev_filter=--all
104 104
105 105 ## RSS feed options
106 106 rss_cut_off_limit = 256000
107 107 rss_items_per_page = 10
108 108 rss_include_diff = false
109 109
110 ## show hash options for changelog
111 sha_len = 12
112 sha_show_numeric_rev = true
110 ## options for showing and identifying changesets
111 show_sha_length = 12
112 show_revision_number = true
113 113
114 114
115 115 ## alternative_gravatar_url allows you to use your own avatar server application
116 116 ## the following parts of the URL will be replaced
117 117 ## {email} user email
118 118 ## {md5email} md5 hash of the user email (like at gravatar.com)
119 119 ## {size} size of the image that is expected from the server application
120 120 ## {scheme} http/https from RhodeCode server
121 121 ## {netloc} network location from RhodeCode server
122 122 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
123 123 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
124 124
125 125
126 126 ## container auth options
127 127 container_auth_enabled = false
128 128 proxypass_auth_enabled = false
129 129
130 130 ## default encoding used to convert from and to unicode
131 131 ## can be also a comma seperated list of encoding in case of mixed encodings
132 132 default_encoding = utf8
133 133
134 134 ## overwrite schema of clone url
135 135 ## available vars:
136 136 ## scheme - http/https
137 137 ## user - current user
138 138 ## pass - password
139 139 ## netloc - network location
140 140 ## path - usually repo_name
141 141
142 142 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
143 143
144 144 ## issue tracking mapping for commits messages
145 145 ## comment out issue_pat, issue_server, issue_prefix to enable
146 146
147 147 ## pattern to get the issues from commit messages
148 148 ## default one used here is #<numbers> with a regex passive group for `#`
149 149 ## {id} will be all groups matched from this pattern
150 150
151 151 issue_pat = (?:\s*#)(\d+)
152 152
153 153 ## server url to the issue, each {id} will be replaced with match
154 154 ## fetched from the regex and {repo} is replaced with full repository name
155 155 ## including groups {repo_name} is replaced with just name of repo
156 156
157 157 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
158 158
159 159 ## prefix to add to link to indicate it's an url
160 160 ## #314 will be replaced by <issue_prefix><id>
161 161
162 162 issue_prefix = #
163 163
164 164 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
165 165 ## multiple patterns, to other issues server, wiki or others
166 166 ## below an example how to create a wiki pattern
167 167 # #wiki-some-id -> https://mywiki.com/some-id
168 168
169 169 #issue_pat_wiki = (?:wiki-)(.+)
170 170 #issue_server_link_wiki = https://mywiki.com/{id}
171 171 #issue_prefix_wiki = WIKI-
172 172
173 173
174 174 ## instance-id prefix
175 175 ## a prefix key for this instance used for cache invalidation when running
176 176 ## multiple instances of rhodecode, make sure it's globally unique for
177 177 ## all running rhodecode instances. Leave empty if you don't use it
178 178 instance_id =
179 179
180 180 ## alternative return HTTP header for failed authentication. Default HTTP
181 181 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
182 182 ## handling that. Set this variable to 403 to return HTTPForbidden
183 183 auth_ret_code =
184 184
185 185 ## locking return code. When repository is locked return this HTTP code. 2XX
186 186 ## codes don't break the transactions while 4XX codes do
187 187 lock_ret_code = 423
188 188
189 189
190 190 ####################################
191 191 ### CELERY CONFIG ####
192 192 ####################################
193 193 use_celery = false
194 194 broker.host = localhost
195 195 broker.vhost = rabbitmqhost
196 196 broker.port = 5672
197 197 broker.user = rabbitmq
198 198 broker.password = qweqwe
199 199
200 200 celery.imports = rhodecode.lib.celerylib.tasks
201 201
202 202 celery.result.backend = amqp
203 203 celery.result.dburi = amqp://
204 204 celery.result.serialier = json
205 205
206 206 #celery.send.task.error.emails = true
207 207 #celery.amqp.task.result.expires = 18000
208 208
209 209 celeryd.concurrency = 2
210 210 #celeryd.log.file = celeryd.log
211 211 celeryd.log.level = debug
212 212 celeryd.max.tasks.per.child = 1
213 213
214 214 ## tasks will never be sent to the queue, but executed locally instead.
215 215 celery.always.eager = false
216 216
217 217 ####################################
218 218 ### BEAKER CACHE ####
219 219 ####################################
220 220 beaker.cache.data_dir=%(here)s/data/cache/data
221 221 beaker.cache.lock_dir=%(here)s/data/cache/lock
222 222
223 223 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
224 224
225 225 beaker.cache.super_short_term.type=memory
226 226 beaker.cache.super_short_term.expire=10
227 227 beaker.cache.super_short_term.key_length = 256
228 228
229 229 beaker.cache.short_term.type=memory
230 230 beaker.cache.short_term.expire=60
231 231 beaker.cache.short_term.key_length = 256
232 232
233 233 beaker.cache.long_term.type=memory
234 234 beaker.cache.long_term.expire=36000
235 235 beaker.cache.long_term.key_length = 256
236 236
237 237 beaker.cache.sql_cache_short.type=memory
238 238 beaker.cache.sql_cache_short.expire=10
239 239 beaker.cache.sql_cache_short.key_length = 256
240 240
241 241 beaker.cache.sql_cache_med.type=memory
242 242 beaker.cache.sql_cache_med.expire=360
243 243 beaker.cache.sql_cache_med.key_length = 256
244 244
245 245 beaker.cache.sql_cache_long.type=file
246 246 beaker.cache.sql_cache_long.expire=3600
247 247 beaker.cache.sql_cache_long.key_length = 256
248 248
249 249 ####################################
250 250 ### BEAKER SESSION ####
251 251 ####################################
252 252 ## Type of storage used for the session, current types are
253 253 ## dbm, file, memcached, database, and memory.
254 254 ## The storage uses the Container API
255 255 ## that is also used by the cache system.
256 256
257 257 ## db session ##
258 258 #beaker.session.type = ext:database
259 259 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
260 260 #beaker.session.table_name = db_session
261 261
262 262 ## encrypted cookie client side session, good for many instances ##
263 263 #beaker.session.type = cookie
264 264
265 265 ## file based cookies (default) ##
266 266 #beaker.session.type = file
267 267
268 268
269 269 beaker.session.key = rhodecode
270 270 ## secure cookie requires AES python libraries
271 271 #beaker.session.encrypt_key = <key_for_encryption>
272 272 #beaker.session.validate_key = <validation_key>
273 273
274 274 ## sets session as invalid if it haven't been accessed for given amount of time
275 275 beaker.session.timeout = 2592000
276 276 beaker.session.httponly = true
277 277 #beaker.session.cookie_path = /<your-prefix>
278 278
279 279 ## uncomment for https secure cookie
280 280 beaker.session.secure = false
281 281
282 282 ## auto save the session to not to use .save()
283 283 beaker.session.auto = False
284 284
285 285 ## default cookie expiration time in seconds `true` expire at browser close ##
286 286 #beaker.session.cookie_expires = 3600
287 287
288 288
289 289 ############################
290 290 ## ERROR HANDLING SYSTEMS ##
291 291 ############################
292 292
293 293 ####################
294 294 ### [errormator] ###
295 295 ####################
296 296
297 297 ## Errormator is tailored to work with RhodeCode, see
298 298 ## http://errormator.com for details how to obtain an account
299 299 ## you must install python package `errormator_client` to make it work
300 300
301 301 ## errormator enabled
302 302 errormator = false
303 303
304 304 errormator.server_url = https://api.errormator.com
305 305 errormator.api_key = YOUR_API_KEY
306 306
307 307 ## TWEAK AMOUNT OF INFO SENT HERE
308 308
309 309 ## enables 404 error logging (default False)
310 310 errormator.report_404 = false
311 311
312 312 ## time in seconds after request is considered being slow (default 1)
313 313 errormator.slow_request_time = 1
314 314
315 315 ## record slow requests in application
316 316 ## (needs to be enabled for slow datastore recording and time tracking)
317 317 errormator.slow_requests = true
318 318
319 319 ## enable hooking to application loggers
320 320 # errormator.logging = true
321 321
322 322 ## minimum log level for log capture
323 323 # errormator.logging.level = WARNING
324 324
325 325 ## send logs only from erroneous/slow requests
326 326 ## (saves API quota for intensive logging)
327 327 errormator.logging_on_error = false
328 328
329 329 ## list of additonal keywords that should be grabbed from environ object
330 330 ## can be string with comma separated list of words in lowercase
331 331 ## (by default client will always send following info:
332 332 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
333 333 ## start with HTTP* this list be extended with additional keywords here
334 334 errormator.environ_keys_whitelist =
335 335
336 336
337 337 ## list of keywords that should be blanked from request object
338 338 ## can be string with comma separated list of words in lowercase
339 339 ## (by default client will always blank keys that contain following words
340 340 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
341 341 ## this list be extended with additional keywords set here
342 342 errormator.request_keys_blacklist =
343 343
344 344
345 345 ## list of namespaces that should be ignores when gathering log entries
346 346 ## can be string with comma separated list of namespaces
347 347 ## (by default the client ignores own entries: errormator_client.client)
348 348 errormator.log_namespace_blacklist =
349 349
350 350
351 351 ################
352 352 ### [sentry] ###
353 353 ################
354 354
355 355 ## sentry is a alternative open source error aggregator
356 356 ## you must install python packages `sentry` and `raven` to enable
357 357
358 358 sentry.dsn = YOUR_DNS
359 359 sentry.servers =
360 360 sentry.name =
361 361 sentry.key =
362 362 sentry.public_key =
363 363 sentry.secret_key =
364 364 sentry.project =
365 365 sentry.site =
366 366 sentry.include_paths =
367 367 sentry.exclude_paths =
368 368
369 369
370 370 ################################################################################
371 371 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
372 372 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
373 373 ## execute malicious code after an exception is raised. ##
374 374 ################################################################################
375 375 set debug = false
376 376
377 377 ##################################
378 378 ### LOGVIEW CONFIG ###
379 379 ##################################
380 380 logview.sqlalchemy = #faa
381 381 logview.pylons.templating = #bfb
382 382 logview.pylons.util = #eee
383 383
384 384 #########################################################
385 385 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
386 386 #########################################################
387 387
388 388 # SQLITE [default]
389 389 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
390 390
391 391 # POSTGRESQL
392 392 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
393 393
394 394 # MySQL
395 395 # sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
396 396
397 397 # see sqlalchemy docs for others
398 398
399 399 sqlalchemy.db1.echo = false
400 400 sqlalchemy.db1.pool_recycle = 3600
401 401 sqlalchemy.db1.convert_unicode = true
402 402
403 403 ################################
404 404 ### LOGGING CONFIGURATION ####
405 405 ################################
406 406 [loggers]
407 407 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
408 408
409 409 [handlers]
410 410 keys = console, console_sql
411 411
412 412 [formatters]
413 413 keys = generic, color_formatter, color_formatter_sql
414 414
415 415 #############
416 416 ## LOGGERS ##
417 417 #############
418 418 [logger_root]
419 419 level = NOTSET
420 420 handlers = console
421 421
422 422 [logger_routes]
423 423 level = DEBUG
424 424 handlers =
425 425 qualname = routes.middleware
426 426 ## "level = DEBUG" logs the route matched and routing variables.
427 427 propagate = 1
428 428
429 429 [logger_beaker]
430 430 level = DEBUG
431 431 handlers =
432 432 qualname = beaker.container
433 433 propagate = 1
434 434
435 435 [logger_templates]
436 436 level = INFO
437 437 handlers =
438 438 qualname = pylons.templating
439 439 propagate = 1
440 440
441 441 [logger_rhodecode]
442 442 level = DEBUG
443 443 handlers =
444 444 qualname = rhodecode
445 445 propagate = 1
446 446
447 447 [logger_sqlalchemy]
448 448 level = INFO
449 449 handlers = console_sql
450 450 qualname = sqlalchemy.engine
451 451 propagate = 0
452 452
453 453 [logger_whoosh_indexer]
454 454 level = DEBUG
455 455 handlers =
456 456 qualname = whoosh_indexer
457 457 propagate = 1
458 458
459 459 ##############
460 460 ## HANDLERS ##
461 461 ##############
462 462
463 463 [handler_console]
464 464 class = StreamHandler
465 465 args = (sys.stderr,)
466 466 level = INFO
467 467 formatter = generic
468 468
469 469 [handler_console_sql]
470 470 class = StreamHandler
471 471 args = (sys.stderr,)
472 472 level = WARN
473 473 formatter = generic
474 474
475 475 ################
476 476 ## FORMATTERS ##
477 477 ################
478 478
479 479 [formatter_generic]
480 480 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
481 481 datefmt = %Y-%m-%d %H:%M:%S
482 482
483 483 [formatter_color_formatter]
484 484 class=rhodecode.lib.colored_formatter.ColorFormatter
485 485 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
486 486 datefmt = %Y-%m-%d %H:%M:%S
487 487
488 488 [formatter_color_formatter_sql]
489 489 class=rhodecode.lib.colored_formatter.ColorFormatterSql
490 490 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
491 491 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,1207 +1,1207 b''
1 1 """Helper functions
2 2
3 3 Consists of functions to typically be used within templates, but also
4 4 available to Controllers. This module is available to both as 'h'.
5 5 """
6 6 import random
7 7 import hashlib
8 8 import StringIO
9 9 import urllib
10 10 import math
11 11 import logging
12 12 import re
13 13 import urlparse
14 14 import textwrap
15 15
16 16 from datetime import datetime
17 17 from pygments.formatters.html import HtmlFormatter
18 18 from pygments import highlight as code_highlight
19 19 from pylons import url, request, config
20 20 from pylons.i18n.translation import _, ungettext
21 21 from hashlib import md5
22 22
23 23 from webhelpers.html import literal, HTML, escape
24 24 from webhelpers.html.tools import *
25 25 from webhelpers.html.builder import make_tag
26 26 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
27 27 end_form, file, form, hidden, image, javascript_link, link_to, \
28 28 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
29 29 submit, text, password, textarea, title, ul, xml_declaration, radio
30 30 from webhelpers.html.tools import auto_link, button_to, highlight, \
31 31 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
32 32 from webhelpers.number import format_byte_size, format_bit_size
33 33 from webhelpers.pylonslib import Flash as _Flash
34 34 from webhelpers.pylonslib.secure_form import secure_form
35 35 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
36 36 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
37 37 replace_whitespace, urlify, truncate, wrap_paragraphs
38 38 from webhelpers.date import time_ago_in_words
39 39 from webhelpers.paginate import Page
40 40 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
41 41 convert_boolean_attrs, NotGiven, _make_safe_id_component
42 42
43 43 from rhodecode.lib.annotate import annotate_highlight
44 44 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
45 45 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
46 46 get_changeset_safe, datetime_to_time, time_to_datetime, AttributeDict,\
47 47 safe_int
48 48 from rhodecode.lib.markup_renderer import MarkupRenderer
49 49 from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError
50 50 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
51 51 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
52 52 from rhodecode.model.changeset_status import ChangesetStatusModel
53 53 from rhodecode.model.db import URL_SEP, Permission
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57
58 58 html_escape_table = {
59 59 "&": "&amp;",
60 60 '"': "&quot;",
61 61 "'": "&apos;",
62 62 ">": "&gt;",
63 63 "<": "&lt;",
64 64 }
65 65
66 66
67 67 def html_escape(text):
68 68 """Produce entities within text."""
69 69 return "".join(html_escape_table.get(c, c) for c in text)
70 70
71 71
72 72 def shorter(text, size=20):
73 73 postfix = '...'
74 74 if len(text) > size:
75 75 return text[:size - len(postfix)] + postfix
76 76 return text
77 77
78 78
79 79 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
80 80 """
81 81 Reset button
82 82 """
83 83 _set_input_attrs(attrs, type, name, value)
84 84 _set_id_attr(attrs, id, name)
85 85 convert_boolean_attrs(attrs, ["disabled"])
86 86 return HTML.input(**attrs)
87 87
88 88 reset = _reset
89 89 safeid = _make_safe_id_component
90 90
91 91
92 92 def FID(raw_id, path):
93 93 """
94 94 Creates a uniqe ID for filenode based on it's hash of path and revision
95 95 it's safe to use in urls
96 96
97 97 :param raw_id:
98 98 :param path:
99 99 """
100 100
101 101 return 'C-%s-%s' % (short_id(raw_id), md5(safe_str(path)).hexdigest()[:12])
102 102
103 103
104 104 def get_token():
105 105 """Return the current authentication token, creating one if one doesn't
106 106 already exist.
107 107 """
108 108 token_key = "_authentication_token"
109 109 from pylons import session
110 110 if not token_key in session:
111 111 try:
112 112 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
113 113 except AttributeError: # Python < 2.4
114 114 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
115 115 session[token_key] = token
116 116 if hasattr(session, 'save'):
117 117 session.save()
118 118 return session[token_key]
119 119
120 120
121 121 class _GetError(object):
122 122 """Get error from form_errors, and represent it as span wrapped error
123 123 message
124 124
125 125 :param field_name: field to fetch errors for
126 126 :param form_errors: form errors dict
127 127 """
128 128
129 129 def __call__(self, field_name, form_errors):
130 130 tmpl = """<span class="error_msg">%s</span>"""
131 131 if form_errors and field_name in form_errors:
132 132 return literal(tmpl % form_errors.get(field_name))
133 133
134 134 get_error = _GetError()
135 135
136 136
137 137 class _ToolTip(object):
138 138
139 139 def __call__(self, tooltip_title, trim_at=50):
140 140 """
141 141 Special function just to wrap our text into nice formatted
142 142 autowrapped text
143 143
144 144 :param tooltip_title:
145 145 """
146 146 tooltip_title = escape(tooltip_title)
147 147 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
148 148 return tooltip_title
149 149 tooltip = _ToolTip()
150 150
151 151
152 152 class _FilesBreadCrumbs(object):
153 153
154 154 def __call__(self, repo_name, rev, paths):
155 155 if isinstance(paths, str):
156 156 paths = safe_unicode(paths)
157 157 url_l = [link_to(repo_name, url('files_home',
158 158 repo_name=repo_name,
159 159 revision=rev, f_path=''),
160 160 class_='ypjax-link')]
161 161 paths_l = paths.split('/')
162 162 for cnt, p in enumerate(paths_l):
163 163 if p != '':
164 164 url_l.append(link_to(p,
165 165 url('files_home',
166 166 repo_name=repo_name,
167 167 revision=rev,
168 168 f_path='/'.join(paths_l[:cnt + 1])
169 169 ),
170 170 class_='ypjax-link'
171 171 )
172 172 )
173 173
174 174 return literal('/'.join(url_l))
175 175
176 176 files_breadcrumbs = _FilesBreadCrumbs()
177 177
178 178
179 179 class CodeHtmlFormatter(HtmlFormatter):
180 180 """
181 181 My code Html Formatter for source codes
182 182 """
183 183
184 184 def wrap(self, source, outfile):
185 185 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
186 186
187 187 def _wrap_code(self, source):
188 188 for cnt, it in enumerate(source):
189 189 i, t = it
190 190 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
191 191 yield i, t
192 192
193 193 def _wrap_tablelinenos(self, inner):
194 194 dummyoutfile = StringIO.StringIO()
195 195 lncount = 0
196 196 for t, line in inner:
197 197 if t:
198 198 lncount += 1
199 199 dummyoutfile.write(line)
200 200
201 201 fl = self.linenostart
202 202 mw = len(str(lncount + fl - 1))
203 203 sp = self.linenospecial
204 204 st = self.linenostep
205 205 la = self.lineanchors
206 206 aln = self.anchorlinenos
207 207 nocls = self.noclasses
208 208 if sp:
209 209 lines = []
210 210
211 211 for i in range(fl, fl + lncount):
212 212 if i % st == 0:
213 213 if i % sp == 0:
214 214 if aln:
215 215 lines.append('<a href="#%s%d" class="special">%*d</a>' %
216 216 (la, i, mw, i))
217 217 else:
218 218 lines.append('<span class="special">%*d</span>' % (mw, i))
219 219 else:
220 220 if aln:
221 221 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
222 222 else:
223 223 lines.append('%*d' % (mw, i))
224 224 else:
225 225 lines.append('')
226 226 ls = '\n'.join(lines)
227 227 else:
228 228 lines = []
229 229 for i in range(fl, fl + lncount):
230 230 if i % st == 0:
231 231 if aln:
232 232 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
233 233 else:
234 234 lines.append('%*d' % (mw, i))
235 235 else:
236 236 lines.append('')
237 237 ls = '\n'.join(lines)
238 238
239 239 # in case you wonder about the seemingly redundant <div> here: since the
240 240 # content in the other cell also is wrapped in a div, some browsers in
241 241 # some configurations seem to mess up the formatting...
242 242 if nocls:
243 243 yield 0, ('<table class="%stable">' % self.cssclass +
244 244 '<tr><td><div class="linenodiv" '
245 245 'style="background-color: #f0f0f0; padding-right: 10px">'
246 246 '<pre style="line-height: 125%">' +
247 247 ls + '</pre></div></td><td id="hlcode" class="code">')
248 248 else:
249 249 yield 0, ('<table class="%stable">' % self.cssclass +
250 250 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
251 251 ls + '</pre></div></td><td id="hlcode" class="code">')
252 252 yield 0, dummyoutfile.getvalue()
253 253 yield 0, '</td></tr></table>'
254 254
255 255
256 256 def pygmentize(filenode, **kwargs):
257 257 """
258 258 pygmentize function using pygments
259 259
260 260 :param filenode:
261 261 """
262 262 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
263 263 return literal(code_highlight(filenode.content, lexer,
264 264 CodeHtmlFormatter(**kwargs)))
265 265
266 266
267 267 def pygmentize_annotation(repo_name, filenode, **kwargs):
268 268 """
269 269 pygmentize function for annotation
270 270
271 271 :param filenode:
272 272 """
273 273
274 274 color_dict = {}
275 275
276 276 def gen_color(n=10000):
277 277 """generator for getting n of evenly distributed colors using
278 278 hsv color and golden ratio. It always return same order of colors
279 279
280 280 :returns: RGB tuple
281 281 """
282 282
283 283 def hsv_to_rgb(h, s, v):
284 284 if s == 0.0:
285 285 return v, v, v
286 286 i = int(h * 6.0) # XXX assume int() truncates!
287 287 f = (h * 6.0) - i
288 288 p = v * (1.0 - s)
289 289 q = v * (1.0 - s * f)
290 290 t = v * (1.0 - s * (1.0 - f))
291 291 i = i % 6
292 292 if i == 0:
293 293 return v, t, p
294 294 if i == 1:
295 295 return q, v, p
296 296 if i == 2:
297 297 return p, v, t
298 298 if i == 3:
299 299 return p, q, v
300 300 if i == 4:
301 301 return t, p, v
302 302 if i == 5:
303 303 return v, p, q
304 304
305 305 golden_ratio = 0.618033988749895
306 306 h = 0.22717784590367374
307 307
308 308 for _ in xrange(n):
309 309 h += golden_ratio
310 310 h %= 1
311 311 HSV_tuple = [h, 0.95, 0.95]
312 312 RGB_tuple = hsv_to_rgb(*HSV_tuple)
313 313 yield map(lambda x: str(int(x * 256)), RGB_tuple)
314 314
315 315 cgenerator = gen_color()
316 316
317 317 def get_color_string(cs):
318 318 if cs in color_dict:
319 319 col = color_dict[cs]
320 320 else:
321 321 col = color_dict[cs] = cgenerator.next()
322 322 return "color: rgb(%s)! important;" % (', '.join(col))
323 323
324 324 def url_func(repo_name):
325 325
326 326 def _url_func(changeset):
327 327 author = changeset.author
328 328 date = changeset.date
329 329 message = tooltip(changeset.message)
330 330
331 331 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
332 332 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
333 333 "</b> %s<br/></div>")
334 334
335 335 tooltip_html = tooltip_html % (author, date, message)
336 336 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
337 337 short_id(changeset.raw_id))
338 338 uri = link_to(
339 339 lnk_format,
340 340 url('changeset_home', repo_name=repo_name,
341 341 revision=changeset.raw_id),
342 342 style=get_color_string(changeset.raw_id),
343 343 class_='tooltip',
344 344 title=tooltip_html
345 345 )
346 346
347 347 uri += '\n'
348 348 return uri
349 349 return _url_func
350 350
351 351 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
352 352
353 353
354 354 def is_following_repo(repo_name, user_id):
355 355 from rhodecode.model.scm import ScmModel
356 356 return ScmModel().is_following_repo(repo_name, user_id)
357 357
358 358 flash = _Flash()
359 359
360 360 #==============================================================================
361 361 # SCM FILTERS available via h.
362 362 #==============================================================================
363 363 from rhodecode.lib.vcs.utils import author_name, author_email
364 364 from rhodecode.lib.utils2 import credentials_filter, age as _age
365 365 from rhodecode.model.db import User, ChangesetStatus
366 366
367 367 age = lambda x, y=False: _age(x, y)
368 368 capitalize = lambda x: x.capitalize()
369 369 email = author_email
370 370 short_id = lambda x: x[:12]
371 371 hide_credentials = lambda x: ''.join(credentials_filter(x))
372 372
373 373
374 374 def show_id(cs):
375 375 """
376 376 Configurable function that shows ID
377 377 by default it's r123:fffeeefffeee
378 378
379 379 :param cs: changeset instance
380 380 """
381 381 from rhodecode import CONFIG
382 def_len = safe_int(CONFIG.get('sha_len', 12))
383 show_rev = str2bool(CONFIG.get('sha_show_numeric_rev', True))
382 def_len = safe_int(CONFIG.get('show_sha_length', 12))
383 show_rev = str2bool(CONFIG.get('show_revision_number', True))
384 384
385 385 raw_id = cs.raw_id[:def_len]
386 386 if show_rev:
387 387 return 'r%s:%s' % (cs.revision, raw_id)
388 388 else:
389 389 return '%s' % (raw_id)
390 390
391 391
392 392 def fmt_date(date):
393 393 if date:
394 394 _fmt = _(u"%a, %d %b %Y %H:%M:%S").encode('utf8')
395 395 return date.strftime(_fmt).decode('utf8')
396 396
397 397 return ""
398 398
399 399
400 400 def is_git(repository):
401 401 if hasattr(repository, 'alias'):
402 402 _type = repository.alias
403 403 elif hasattr(repository, 'repo_type'):
404 404 _type = repository.repo_type
405 405 else:
406 406 _type = repository
407 407 return _type == 'git'
408 408
409 409
410 410 def is_hg(repository):
411 411 if hasattr(repository, 'alias'):
412 412 _type = repository.alias
413 413 elif hasattr(repository, 'repo_type'):
414 414 _type = repository.repo_type
415 415 else:
416 416 _type = repository
417 417 return _type == 'hg'
418 418
419 419
420 420 def email_or_none(author):
421 421 # extract email from the commit string
422 422 _email = email(author)
423 423 if _email != '':
424 424 # check it against RhodeCode database, and use the MAIN email for this
425 425 # user
426 426 user = User.get_by_email(_email, case_insensitive=True, cache=True)
427 427 if user is not None:
428 428 return user.email
429 429 return _email
430 430
431 431 # See if it contains a username we can get an email from
432 432 user = User.get_by_username(author_name(author), case_insensitive=True,
433 433 cache=True)
434 434 if user is not None:
435 435 return user.email
436 436
437 437 # No valid email, not a valid user in the system, none!
438 438 return None
439 439
440 440
441 441 def person(author, show_attr="username_and_name"):
442 442 # attr to return from fetched user
443 443 person_getter = lambda usr: getattr(usr, show_attr)
444 444
445 445 # Valid email in the attribute passed, see if they're in the system
446 446 _email = email(author)
447 447 if _email != '':
448 448 user = User.get_by_email(_email, case_insensitive=True, cache=True)
449 449 if user is not None:
450 450 return person_getter(user)
451 451 return _email
452 452
453 453 # Maybe it's a username?
454 454 _author = author_name(author)
455 455 user = User.get_by_username(_author, case_insensitive=True,
456 456 cache=True)
457 457 if user is not None:
458 458 return person_getter(user)
459 459
460 460 # Still nothing? Just pass back the author name then
461 461 return _author
462 462
463 463
464 464 def person_by_id(id_, show_attr="username_and_name"):
465 465 # attr to return from fetched user
466 466 person_getter = lambda usr: getattr(usr, show_attr)
467 467
468 468 #maybe it's an ID ?
469 469 if str(id_).isdigit() or isinstance(id_, int):
470 470 id_ = int(id_)
471 471 user = User.get(id_)
472 472 if user is not None:
473 473 return person_getter(user)
474 474 return id_
475 475
476 476
477 477 def desc_stylize(value):
478 478 """
479 479 converts tags from value into html equivalent
480 480
481 481 :param value:
482 482 """
483 483 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
484 484 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
485 485 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
486 486 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
487 487 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z0-9\-\/]*)\]',
488 488 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
489 489 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]',
490 490 '<div class="metatag" tag="lang">\\2</div>', value)
491 491 value = re.sub(r'\[([a-z]+)\]',
492 492 '<div class="metatag" tag="\\1">\\1</div>', value)
493 493
494 494 return value
495 495
496 496
497 497 def boolicon(value):
498 498 """Returns boolean value of a value, represented as small html image of true/false
499 499 icons
500 500
501 501 :param value: value
502 502 """
503 503
504 504 if value:
505 505 return HTML.tag('img', src=url("/images/icons/accept.png"),
506 506 alt=_('True'))
507 507 else:
508 508 return HTML.tag('img', src=url("/images/icons/cancel.png"),
509 509 alt=_('False'))
510 510
511 511
512 512 def action_parser(user_log, feed=False, parse_cs=False):
513 513 """
514 514 This helper will action_map the specified string action into translated
515 515 fancy names with icons and links
516 516
517 517 :param user_log: user log instance
518 518 :param feed: use output for feeds (no html and fancy icons)
519 519 :param parse_cs: parse Changesets into VCS instances
520 520 """
521 521
522 522 action = user_log.action
523 523 action_params = ' '
524 524
525 525 x = action.split(':')
526 526
527 527 if len(x) > 1:
528 528 action, action_params = x
529 529
530 530 def get_cs_links():
531 531 revs_limit = 3 # display this amount always
532 532 revs_top_limit = 50 # show upto this amount of changesets hidden
533 533 revs_ids = action_params.split(',')
534 534 deleted = user_log.repository is None
535 535 if deleted:
536 536 return ','.join(revs_ids)
537 537
538 538 repo_name = user_log.repository.repo_name
539 539
540 540 def lnk(rev, repo_name):
541 541 if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict):
542 542 lazy_cs = True
543 543 if getattr(rev, 'op', None) and getattr(rev, 'ref_name', None):
544 544 lazy_cs = False
545 545 lbl = '?'
546 546 if rev.op == 'delete_branch':
547 547 lbl = '%s' % _('Deleted branch: %s') % rev.ref_name
548 548 title = ''
549 549 elif rev.op == 'tag':
550 550 lbl = '%s' % _('Created tag: %s') % rev.ref_name
551 551 title = ''
552 552 _url = '#'
553 553
554 554 else:
555 555 lbl = '%s' % (rev.short_id[:8])
556 556 _url = url('changeset_home', repo_name=repo_name,
557 557 revision=rev.raw_id)
558 558 title = tooltip(rev.message)
559 559 else:
560 560 ## changeset cannot be found/striped/removed etc.
561 561 lbl = ('%s' % rev)[:12]
562 562 _url = '#'
563 563 title = _('Changeset not found')
564 564 if parse_cs:
565 565 return link_to(lbl, _url, title=title, class_='tooltip')
566 566 return link_to(lbl, _url, raw_id=rev.raw_id, repo_name=repo_name,
567 567 class_='lazy-cs' if lazy_cs else '')
568 568
569 569 def _get_op(rev_txt):
570 570 _op = None
571 571 _name = rev_txt
572 572 if len(rev_txt.split('=>')) == 2:
573 573 _op, _name = rev_txt.split('=>')
574 574 return _op, _name
575 575
576 576 revs = []
577 577 if len(filter(lambda v: v != '', revs_ids)) > 0:
578 578 repo = None
579 579 for rev in revs_ids[:revs_top_limit]:
580 580 _op, _name = _get_op(rev)
581 581
582 582 # we want parsed changesets, or new log store format is bad
583 583 if parse_cs:
584 584 try:
585 585 if repo is None:
586 586 repo = user_log.repository.scm_instance
587 587 _rev = repo.get_changeset(rev)
588 588 revs.append(_rev)
589 589 except ChangesetDoesNotExistError:
590 590 log.error('cannot find revision %s in this repo' % rev)
591 591 revs.append(rev)
592 592 continue
593 593 else:
594 594 _rev = AttributeDict({
595 595 'short_id': rev[:12],
596 596 'raw_id': rev,
597 597 'message': '',
598 598 'op': _op,
599 599 'ref_name': _name
600 600 })
601 601 revs.append(_rev)
602 602 cs_links = []
603 603 cs_links.append(" " + ', '.join(
604 604 [lnk(rev, repo_name) for rev in revs[:revs_limit]]
605 605 )
606 606 )
607 607 _op1, _name1 = _get_op(revs_ids[0])
608 608 _op2, _name2 = _get_op(revs_ids[-1])
609 609
610 610 _rev = '%s...%s' % (_name1, _name2)
611 611
612 612 compare_view = (
613 613 ' <div class="compare_view tooltip" title="%s">'
614 614 '<a href="%s">%s</a> </div>' % (
615 615 _('Show all combined changesets %s->%s') % (
616 616 revs_ids[0][:12], revs_ids[-1][:12]
617 617 ),
618 618 url('changeset_home', repo_name=repo_name,
619 619 revision=_rev
620 620 ),
621 621 _('compare view')
622 622 )
623 623 )
624 624
625 625 # if we have exactly one more than normally displayed
626 626 # just display it, takes less space than displaying
627 627 # "and 1 more revisions"
628 628 if len(revs_ids) == revs_limit + 1:
629 629 rev = revs[revs_limit]
630 630 cs_links.append(", " + lnk(rev, repo_name))
631 631
632 632 # hidden-by-default ones
633 633 if len(revs_ids) > revs_limit + 1:
634 634 uniq_id = revs_ids[0]
635 635 html_tmpl = (
636 636 '<span> %s <a class="show_more" id="_%s" '
637 637 'href="#more">%s</a> %s</span>'
638 638 )
639 639 if not feed:
640 640 cs_links.append(html_tmpl % (
641 641 _('and'),
642 642 uniq_id, _('%s more') % (len(revs_ids) - revs_limit),
643 643 _('revisions')
644 644 )
645 645 )
646 646
647 647 if not feed:
648 648 html_tmpl = '<span id="%s" style="display:none">, %s </span>'
649 649 else:
650 650 html_tmpl = '<span id="%s"> %s </span>'
651 651
652 652 morelinks = ', '.join(
653 653 [lnk(rev, repo_name) for rev in revs[revs_limit:]]
654 654 )
655 655
656 656 if len(revs_ids) > revs_top_limit:
657 657 morelinks += ', ...'
658 658
659 659 cs_links.append(html_tmpl % (uniq_id, morelinks))
660 660 if len(revs) > 1:
661 661 cs_links.append(compare_view)
662 662 return ''.join(cs_links)
663 663
664 664 def get_fork_name():
665 665 repo_name = action_params
666 666 _url = url('summary_home', repo_name=repo_name)
667 667 return _('fork name %s') % link_to(action_params, _url)
668 668
669 669 def get_user_name():
670 670 user_name = action_params
671 671 return user_name
672 672
673 673 def get_users_group():
674 674 group_name = action_params
675 675 return group_name
676 676
677 677 def get_pull_request():
678 678 pull_request_id = action_params
679 679 deleted = user_log.repository is None
680 680 if deleted:
681 681 repo_name = user_log.repository_name
682 682 else:
683 683 repo_name = user_log.repository.repo_name
684 684 return link_to(_('Pull request #%s') % pull_request_id,
685 685 url('pullrequest_show', repo_name=repo_name,
686 686 pull_request_id=pull_request_id))
687 687
688 688 # action : translated str, callback(extractor), icon
689 689 action_map = {
690 690 'user_deleted_repo': (_('[deleted] repository'),
691 691 None, 'database_delete.png'),
692 692 'user_created_repo': (_('[created] repository'),
693 693 None, 'database_add.png'),
694 694 'user_created_fork': (_('[created] repository as fork'),
695 695 None, 'arrow_divide.png'),
696 696 'user_forked_repo': (_('[forked] repository'),
697 697 get_fork_name, 'arrow_divide.png'),
698 698 'user_updated_repo': (_('[updated] repository'),
699 699 None, 'database_edit.png'),
700 700 'admin_deleted_repo': (_('[delete] repository'),
701 701 None, 'database_delete.png'),
702 702 'admin_created_repo': (_('[created] repository'),
703 703 None, 'database_add.png'),
704 704 'admin_forked_repo': (_('[forked] repository'),
705 705 None, 'arrow_divide.png'),
706 706 'admin_updated_repo': (_('[updated] repository'),
707 707 None, 'database_edit.png'),
708 708 'admin_created_user': (_('[created] user'),
709 709 get_user_name, 'user_add.png'),
710 710 'admin_updated_user': (_('[updated] user'),
711 711 get_user_name, 'user_edit.png'),
712 712 'admin_created_users_group': (_('[created] user group'),
713 713 get_users_group, 'group_add.png'),
714 714 'admin_updated_users_group': (_('[updated] user group'),
715 715 get_users_group, 'group_edit.png'),
716 716 'user_commented_revision': (_('[commented] on revision in repository'),
717 717 get_cs_links, 'comment_add.png'),
718 718 'user_commented_pull_request': (_('[commented] on pull request for'),
719 719 get_pull_request, 'comment_add.png'),
720 720 'user_closed_pull_request': (_('[closed] pull request for'),
721 721 get_pull_request, 'tick.png'),
722 722 'push': (_('[pushed] into'),
723 723 get_cs_links, 'script_add.png'),
724 724 'push_local': (_('[committed via RhodeCode] into repository'),
725 725 get_cs_links, 'script_edit.png'),
726 726 'push_remote': (_('[pulled from remote] into repository'),
727 727 get_cs_links, 'connect.png'),
728 728 'pull': (_('[pulled] from'),
729 729 None, 'down_16.png'),
730 730 'started_following_repo': (_('[started following] repository'),
731 731 None, 'heart_add.png'),
732 732 'stopped_following_repo': (_('[stopped following] repository'),
733 733 None, 'heart_delete.png'),
734 734 }
735 735
736 736 action_str = action_map.get(action, action)
737 737 if feed:
738 738 action = action_str[0].replace('[', '').replace(']', '')
739 739 else:
740 740 action = action_str[0]\
741 741 .replace('[', '<span class="journal_highlight">')\
742 742 .replace(']', '</span>')
743 743
744 744 action_params_func = lambda: ""
745 745
746 746 if callable(action_str[1]):
747 747 action_params_func = action_str[1]
748 748
749 749 def action_parser_icon():
750 750 action = user_log.action
751 751 action_params = None
752 752 x = action.split(':')
753 753
754 754 if len(x) > 1:
755 755 action, action_params = x
756 756
757 757 tmpl = """<img src="%s%s" alt="%s"/>"""
758 758 ico = action_map.get(action, ['', '', ''])[2]
759 759 return literal(tmpl % ((url('/images/icons/')), ico, action))
760 760
761 761 # returned callbacks we need to call to get
762 762 return [lambda: literal(action), action_params_func, action_parser_icon]
763 763
764 764
765 765
766 766 #==============================================================================
767 767 # PERMS
768 768 #==============================================================================
769 769 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
770 770 HasRepoPermissionAny, HasRepoPermissionAll, HasReposGroupPermissionAll, \
771 771 HasReposGroupPermissionAny
772 772
773 773
774 774 #==============================================================================
775 775 # GRAVATAR URL
776 776 #==============================================================================
777 777
778 778 def gravatar_url(email_address, size=30):
779 779 from pylons import url # doh, we need to re-import url to mock it later
780 780 _def = 'anonymous@rhodecode.org'
781 781 use_gravatar = str2bool(config['app_conf'].get('use_gravatar'))
782 782 email_address = email_address or _def
783 783 if (not use_gravatar or not email_address or email_address == _def):
784 784 f = lambda a, l: min(l, key=lambda x: abs(x - a))
785 785 return url("/images/user%s.png" % f(size, [14, 16, 20, 24, 30]))
786 786
787 787 if use_gravatar and config['app_conf'].get('alternative_gravatar_url'):
788 788 tmpl = config['app_conf'].get('alternative_gravatar_url', '')
789 789 parsed_url = urlparse.urlparse(url.current(qualified=True))
790 790 tmpl = tmpl.replace('{email}', email_address)\
791 791 .replace('{md5email}', hashlib.md5(email_address.lower()).hexdigest()) \
792 792 .replace('{netloc}', parsed_url.netloc)\
793 793 .replace('{scheme}', parsed_url.scheme)\
794 794 .replace('{size}', str(size))
795 795 return tmpl
796 796
797 797 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
798 798 default = 'identicon'
799 799 baseurl_nossl = "http://www.gravatar.com/avatar/"
800 800 baseurl_ssl = "https://secure.gravatar.com/avatar/"
801 801 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
802 802
803 803 if isinstance(email_address, unicode):
804 804 #hashlib crashes on unicode items
805 805 email_address = safe_str(email_address)
806 806 # construct the url
807 807 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
808 808 gravatar_url += urllib.urlencode({'d': default, 's': str(size)})
809 809
810 810 return gravatar_url
811 811
812 812
813 813 #==============================================================================
814 814 # REPO PAGER, PAGER FOR REPOSITORY
815 815 #==============================================================================
816 816 class RepoPage(Page):
817 817
818 818 def __init__(self, collection, page=1, items_per_page=20,
819 819 item_count=None, url=None, **kwargs):
820 820
821 821 """Create a "RepoPage" instance. special pager for paging
822 822 repository
823 823 """
824 824 self._url_generator = url
825 825
826 826 # Safe the kwargs class-wide so they can be used in the pager() method
827 827 self.kwargs = kwargs
828 828
829 829 # Save a reference to the collection
830 830 self.original_collection = collection
831 831
832 832 self.collection = collection
833 833
834 834 # The self.page is the number of the current page.
835 835 # The first page has the number 1!
836 836 try:
837 837 self.page = int(page) # make it int() if we get it as a string
838 838 except (ValueError, TypeError):
839 839 self.page = 1
840 840
841 841 self.items_per_page = items_per_page
842 842
843 843 # Unless the user tells us how many items the collections has
844 844 # we calculate that ourselves.
845 845 if item_count is not None:
846 846 self.item_count = item_count
847 847 else:
848 848 self.item_count = len(self.collection)
849 849
850 850 # Compute the number of the first and last available page
851 851 if self.item_count > 0:
852 852 self.first_page = 1
853 853 self.page_count = int(math.ceil(float(self.item_count) /
854 854 self.items_per_page))
855 855 self.last_page = self.first_page + self.page_count - 1
856 856
857 857 # Make sure that the requested page number is the range of
858 858 # valid pages
859 859 if self.page > self.last_page:
860 860 self.page = self.last_page
861 861 elif self.page < self.first_page:
862 862 self.page = self.first_page
863 863
864 864 # Note: the number of items on this page can be less than
865 865 # items_per_page if the last page is not full
866 866 self.first_item = max(0, (self.item_count) - (self.page *
867 867 items_per_page))
868 868 self.last_item = ((self.item_count - 1) - items_per_page *
869 869 (self.page - 1))
870 870
871 871 self.items = list(self.collection[self.first_item:self.last_item + 1])
872 872
873 873 # Links to previous and next page
874 874 if self.page > self.first_page:
875 875 self.previous_page = self.page - 1
876 876 else:
877 877 self.previous_page = None
878 878
879 879 if self.page < self.last_page:
880 880 self.next_page = self.page + 1
881 881 else:
882 882 self.next_page = None
883 883
884 884 # No items available
885 885 else:
886 886 self.first_page = None
887 887 self.page_count = 0
888 888 self.last_page = None
889 889 self.first_item = None
890 890 self.last_item = None
891 891 self.previous_page = None
892 892 self.next_page = None
893 893 self.items = []
894 894
895 895 # This is a subclass of the 'list' type. Initialise the list now.
896 896 list.__init__(self, reversed(self.items))
897 897
898 898
899 899 def changed_tooltip(nodes):
900 900 """
901 901 Generates a html string for changed nodes in changeset page.
902 902 It limits the output to 30 entries
903 903
904 904 :param nodes: LazyNodesGenerator
905 905 """
906 906 if nodes:
907 907 pref = ': <br/> '
908 908 suf = ''
909 909 if len(nodes) > 30:
910 910 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
911 911 return literal(pref + '<br/> '.join([safe_unicode(x.path)
912 912 for x in nodes[:30]]) + suf)
913 913 else:
914 914 return ': ' + _('No Files')
915 915
916 916
917 917 def repo_link(groups_and_repos):
918 918 """
919 919 Makes a breadcrumbs link to repo within a group
920 920 joins &raquo; on each group to create a fancy link
921 921
922 922 ex::
923 923 group >> subgroup >> repo
924 924
925 925 :param groups_and_repos:
926 926 :param last_url:
927 927 """
928 928 groups, just_name, repo_name = groups_and_repos
929 929 last_url = url('summary_home', repo_name=repo_name)
930 930 last_link = link_to(just_name, last_url)
931 931
932 932 def make_link(group):
933 933 return link_to(group.name,
934 934 url('repos_group_home', group_name=group.group_name))
935 935 return literal(' &raquo; '.join(map(make_link, groups) + ['<span>%s</span>' % last_link]))
936 936
937 937
938 938 def fancy_file_stats(stats):
939 939 """
940 940 Displays a fancy two colored bar for number of added/deleted
941 941 lines of code on file
942 942
943 943 :param stats: two element list of added/deleted lines of code
944 944 """
945 945 def cgen(l_type, a_v, d_v):
946 946 mapping = {'tr': 'top-right-rounded-corner-mid',
947 947 'tl': 'top-left-rounded-corner-mid',
948 948 'br': 'bottom-right-rounded-corner-mid',
949 949 'bl': 'bottom-left-rounded-corner-mid'}
950 950 map_getter = lambda x: mapping[x]
951 951
952 952 if l_type == 'a' and d_v:
953 953 #case when added and deleted are present
954 954 return ' '.join(map(map_getter, ['tl', 'bl']))
955 955
956 956 if l_type == 'a' and not d_v:
957 957 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
958 958
959 959 if l_type == 'd' and a_v:
960 960 return ' '.join(map(map_getter, ['tr', 'br']))
961 961
962 962 if l_type == 'd' and not a_v:
963 963 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
964 964
965 965 a, d = stats[0], stats[1]
966 966 width = 100
967 967
968 968 if a == 'b':
969 969 #binary mode
970 970 b_d = '<div class="bin%s %s" style="width:100%%">%s</div>' % (d, cgen('a', a_v='', d_v=0), 'bin')
971 971 b_a = '<div class="bin1" style="width:0%%">%s</div>' % ('bin')
972 972 return literal('<div style="width:%spx">%s%s</div>' % (width, b_a, b_d))
973 973
974 974 t = stats[0] + stats[1]
975 975 unit = float(width) / (t or 1)
976 976
977 977 # needs > 9% of width to be visible or 0 to be hidden
978 978 a_p = max(9, unit * a) if a > 0 else 0
979 979 d_p = max(9, unit * d) if d > 0 else 0
980 980 p_sum = a_p + d_p
981 981
982 982 if p_sum > width:
983 983 #adjust the percentage to be == 100% since we adjusted to 9
984 984 if a_p > d_p:
985 985 a_p = a_p - (p_sum - width)
986 986 else:
987 987 d_p = d_p - (p_sum - width)
988 988
989 989 a_v = a if a > 0 else ''
990 990 d_v = d if d > 0 else ''
991 991
992 992 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
993 993 cgen('a', a_v, d_v), a_p, a_v
994 994 )
995 995 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
996 996 cgen('d', a_v, d_v), d_p, d_v
997 997 )
998 998 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
999 999
1000 1000
1001 1001 def urlify_text(text_, safe=True):
1002 1002 """
1003 1003 Extrac urls from text and make html links out of them
1004 1004
1005 1005 :param text_:
1006 1006 """
1007 1007
1008 1008 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
1009 1009 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1010 1010
1011 1011 def url_func(match_obj):
1012 1012 url_full = match_obj.groups()[0]
1013 1013 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1014 1014 _newtext = url_pat.sub(url_func, text_)
1015 1015 if safe:
1016 1016 return literal(_newtext)
1017 1017 return _newtext
1018 1018
1019 1019
1020 1020 def urlify_changesets(text_, repository):
1021 1021 """
1022 1022 Extract revision ids from changeset and make link from them
1023 1023
1024 1024 :param text_:
1025 1025 :param repository: repo name to build the URL with
1026 1026 """
1027 1027 from pylons import url # doh, we need to re-import url to mock it later
1028 1028 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1029 1029
1030 1030 def url_func(match_obj):
1031 1031 rev = match_obj.groups()[1]
1032 1032 pref = match_obj.groups()[0]
1033 1033 suf = match_obj.groups()[2]
1034 1034
1035 1035 tmpl = (
1036 1036 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1037 1037 '%(rev)s</a>%(suf)s'
1038 1038 )
1039 1039 return tmpl % {
1040 1040 'pref': pref,
1041 1041 'cls': 'revision-link',
1042 1042 'url': url('changeset_home', repo_name=repository, revision=rev),
1043 1043 'rev': rev,
1044 1044 'suf': suf
1045 1045 }
1046 1046
1047 1047 newtext = URL_PAT.sub(url_func, text_)
1048 1048
1049 1049 return newtext
1050 1050
1051 1051
1052 1052 def urlify_commit(text_, repository=None, link_=None):
1053 1053 """
1054 1054 Parses given text message and makes proper links.
1055 1055 issues are linked to given issue-server, and rest is a changeset link
1056 1056 if link_ is given, in other case it's a plain text
1057 1057
1058 1058 :param text_:
1059 1059 :param repository:
1060 1060 :param link_: changeset link
1061 1061 """
1062 1062 import traceback
1063 1063 from pylons import url # doh, we need to re-import url to mock it later
1064 1064
1065 1065 def escaper(string):
1066 1066 return string.replace('<', '&lt;').replace('>', '&gt;')
1067 1067
1068 1068 def linkify_others(t, l):
1069 1069 urls = re.compile(r'(\<a.*?\<\/a\>)',)
1070 1070 links = []
1071 1071 for e in urls.split(t):
1072 1072 if not urls.match(e):
1073 1073 links.append('<a class="message-link" href="%s">%s</a>' % (l, e))
1074 1074 else:
1075 1075 links.append(e)
1076 1076
1077 1077 return ''.join(links)
1078 1078
1079 1079 # urlify changesets - extrac revisions and make link out of them
1080 1080 newtext = urlify_changesets(escaper(text_), repository)
1081 1081
1082 1082 # extract http/https links and make them real urls
1083 1083 newtext = urlify_text(newtext, safe=False)
1084 1084
1085 1085 try:
1086 1086 from rhodecode import CONFIG
1087 1087 conf = CONFIG
1088 1088
1089 1089 # allow multiple issue servers to be used
1090 1090 valid_indices = [
1091 1091 x.group(1)
1092 1092 for x in map(lambda x: re.match(r'issue_pat(.*)', x), conf.keys())
1093 1093 if x and 'issue_server_link%s' % x.group(1) in conf
1094 1094 and 'issue_prefix%s' % x.group(1) in conf
1095 1095 ]
1096 1096
1097 1097 log.debug('found issue server suffixes `%s` during valuation of: %s'
1098 1098 % (','.join(valid_indices), newtext))
1099 1099
1100 1100 for pattern_index in valid_indices:
1101 1101 ISSUE_PATTERN = conf.get('issue_pat%s' % pattern_index)
1102 1102 ISSUE_SERVER_LNK = conf.get('issue_server_link%s' % pattern_index)
1103 1103 ISSUE_PREFIX = conf.get('issue_prefix%s' % pattern_index)
1104 1104
1105 1105 log.debug('pattern suffix `%s` PAT:%s SERVER_LINK:%s PREFIX:%s'
1106 1106 % (pattern_index, ISSUE_PATTERN, ISSUE_SERVER_LNK,
1107 1107 ISSUE_PREFIX))
1108 1108
1109 1109 URL_PAT = re.compile(r'%s' % ISSUE_PATTERN)
1110 1110
1111 1111 def url_func(match_obj):
1112 1112 pref = ''
1113 1113 if match_obj.group().startswith(' '):
1114 1114 pref = ' '
1115 1115
1116 1116 issue_id = ''.join(match_obj.groups())
1117 1117 tmpl = (
1118 1118 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1119 1119 '%(issue-prefix)s%(id-repr)s'
1120 1120 '</a>'
1121 1121 )
1122 1122 url = ISSUE_SERVER_LNK.replace('{id}', issue_id)
1123 1123 if repository:
1124 1124 url = url.replace('{repo}', repository)
1125 1125 repo_name = repository.split(URL_SEP)[-1]
1126 1126 url = url.replace('{repo_name}', repo_name)
1127 1127
1128 1128 return tmpl % {
1129 1129 'pref': pref,
1130 1130 'cls': 'issue-tracker-link',
1131 1131 'url': url,
1132 1132 'id-repr': issue_id,
1133 1133 'issue-prefix': ISSUE_PREFIX,
1134 1134 'serv': ISSUE_SERVER_LNK,
1135 1135 }
1136 1136 newtext = URL_PAT.sub(url_func, newtext)
1137 1137 log.debug('processed prefix:`%s` => %s' % (pattern_index, newtext))
1138 1138
1139 1139 # if we actually did something above
1140 1140 if link_:
1141 1141 # wrap not links into final link => link_
1142 1142 newtext = linkify_others(newtext, link_)
1143 1143 except Exception:
1144 1144 log.error(traceback.format_exc())
1145 1145 pass
1146 1146
1147 1147 return literal(newtext)
1148 1148
1149 1149
1150 1150 def rst(source):
1151 1151 return literal('<div class="rst-block">%s</div>' %
1152 1152 MarkupRenderer.rst(source))
1153 1153
1154 1154
1155 1155 def rst_w_mentions(source):
1156 1156 """
1157 1157 Wrapped rst renderer with @mention highlighting
1158 1158
1159 1159 :param source:
1160 1160 """
1161 1161 return literal('<div class="rst-block">%s</div>' %
1162 1162 MarkupRenderer.rst_with_mentions(source))
1163 1163
1164 1164
1165 1165 def changeset_status(repo, revision):
1166 1166 return ChangesetStatusModel().get_status(repo, revision)
1167 1167
1168 1168
1169 1169 def changeset_status_lbl(changeset_status):
1170 1170 return dict(ChangesetStatus.STATUSES).get(changeset_status)
1171 1171
1172 1172
1173 1173 def get_permission_name(key):
1174 1174 return dict(Permission.PERMS).get(key)
1175 1175
1176 1176
1177 1177 def journal_filter_help():
1178 1178 return _(textwrap.dedent('''
1179 1179 Example filter terms:
1180 1180 repository:vcs
1181 1181 username:marcin
1182 1182 action:*push*
1183 1183 ip:127.0.0.1
1184 1184 date:20120101
1185 1185 date:[20120101100000 TO 20120102]
1186 1186
1187 1187 Generate wildcards using '*' character:
1188 1188 "repositroy:vcs*" - search everything starting with 'vcs'
1189 1189 "repository:*vcs*" - search for repository containing 'vcs'
1190 1190
1191 1191 Optional AND / OR operators in queries
1192 1192 "repository:vcs OR repository:test"
1193 1193 "username:test AND repository:test*"
1194 1194 '''))
1195 1195
1196 1196
1197 1197 def not_mapped_error(repo_name):
1198 1198 flash(_('%s repository is not mapped to db perhaps'
1199 1199 ' it was created or renamed from the filesystem'
1200 1200 ' please run the application again'
1201 1201 ' in order to rescan repositories') % repo_name, category='error')
1202 1202
1203 1203
1204 1204 def ip_range(ip_addr):
1205 1205 from rhodecode.model.db import UserIpMap
1206 1206 s, e = UserIpMap._get_ip_range(ip_addr)
1207 1207 return '%s - %s' % (s, e)
@@ -1,482 +1,482 b''
1 1 ################################################################################
2 2 ################################################################################
3 3 # RhodeCode - Pylons environment configuration #
4 4 # #
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 ################################################################################
7 7
8 8 [DEFAULT]
9 9 debug = true
10 10 pdebug = false
11 11 ################################################################################
12 12 ## Uncomment and replace with the address which should receive ##
13 13 ## any error reports after application crash ##
14 14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 15 ################################################################################
16 16 #email_to = admin@localhost
17 17 #error_email_from = paste_error@localhost
18 18 #app_email_from = rhodecode-noreply@localhost
19 19 #error_message =
20 20 #email_prefix = [RhodeCode]
21 21
22 22 #smtp_server = mail.server.com
23 23 #smtp_username =
24 24 #smtp_password =
25 25 #smtp_port =
26 26 #smtp_use_tls = false
27 27 #smtp_use_ssl = true
28 28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 29 #smtp_auth =
30 30
31 31 [server:main]
32 32 ## PASTE
33 33 ## nr of threads to spawn
34 34 #threadpool_workers = 5
35 35
36 36 ## max request before thread respawn
37 37 #threadpool_max_requests = 10
38 38
39 39 ## option to use threads of process
40 40 #use_threadpool = true
41 41
42 42 #use = egg:Paste#http
43 43
44 44 ## WAITRESS
45 45 threads = 5
46 46 ## 100GB
47 47 max_request_body_size = 107374182400
48 48 use = egg:waitress#main
49 49
50 50 host = 127.0.0.1
51 51 port = 5000
52 52
53 53 ## prefix middleware for rc
54 54 #[filter:proxy-prefix]
55 55 #use = egg:PasteDeploy#prefix
56 56 #prefix = /<your-prefix>
57 57
58 58 [app:main]
59 59 use = egg:rhodecode
60 60 ## enable proxy prefix middleware
61 61 #filter-with = proxy-prefix
62 62
63 63 full_stack = true
64 64 static_files = true
65 65 ## Optional Languages
66 66 ## en, fr, ja, pt_BR, zh_CN, zh_TW, pl
67 67 lang = en
68 68 cache_dir = /tmp/rc/data
69 69 index_dir = /tmp/rc/index
70 70
71 71 ## uncomment and set this path to use archive download cache
72 72 #archive_cache_dir = /tmp/tarballcache
73 73
74 74 ## change this to unique ID for security
75 75 app_instance_uuid = rc-production
76 76
77 77 ## cut off limit for large diffs (size in bytes)
78 78 cut_off_limit = 256000
79 79
80 80 ## use cache version of scm repo everywhere
81 81 vcs_full_cache = false
82 82
83 83 ## force https in RhodeCode, fixes https redirects, assumes it's always https
84 84 force_https = false
85 85
86 86 ## use Strict-Transport-Security headers
87 87 use_htsts = false
88 88
89 89 ## number of commits stats will parse on each iteration
90 90 commit_parse_limit = 25
91 91
92 92 ## number of items displayed in lightweight dashboard before paginating is shown
93 93 dashboard_items = 100
94 94
95 95 ## use gravatar service to display avatars
96 96 use_gravatar = true
97 97
98 98 ## path to git executable
99 99 git_path = git
100 100
101 101 ## git rev filter option, --all is the default filter, if you need to
102 102 ## hide all refs in changelog switch this to --branches --tags
103 103 git_rev_filter=--all
104 104
105 105 ## RSS feed options
106 106 rss_cut_off_limit = 256000
107 107 rss_items_per_page = 10
108 108 rss_include_diff = false
109 109
110 ## show hash options for changelog
111 sha_len = 12
112 sha_show_numeric_rev = true
110 ## options for showing and identifying changesets
111 show_sha_length = 12
112 show_revision_number = true
113 113
114 114
115 115 ## alternative_gravatar_url allows you to use your own avatar server application
116 116 ## the following parts of the URL will be replaced
117 117 ## {email} user email
118 118 ## {md5email} md5 hash of the user email (like at gravatar.com)
119 119 ## {size} size of the image that is expected from the server application
120 120 ## {scheme} http/https from RhodeCode server
121 121 ## {netloc} network location from RhodeCode server
122 122 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
123 123 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
124 124
125 125
126 126 ## container auth options
127 127 container_auth_enabled = false
128 128 proxypass_auth_enabled = false
129 129
130 130 ## default encoding used to convert from and to unicode
131 131 ## can be also a comma seperated list of encoding in case of mixed encodings
132 132 default_encoding = utf8
133 133
134 134 ## overwrite schema of clone url
135 135 ## available vars:
136 136 ## scheme - http/https
137 137 ## user - current user
138 138 ## pass - password
139 139 ## netloc - network location
140 140 ## path - usually repo_name
141 141
142 142 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
143 143
144 144 ## issue tracking mapping for commits messages
145 145 ## comment out issue_pat, issue_server, issue_prefix to enable
146 146
147 147 ## pattern to get the issues from commit messages
148 148 ## default one used here is #<numbers> with a regex passive group for `#`
149 149 ## {id} will be all groups matched from this pattern
150 150
151 151 issue_pat = (?:\s*#)(\d+)
152 152
153 153 ## server url to the issue, each {id} will be replaced with match
154 154 ## fetched from the regex and {repo} is replaced with full repository name
155 155 ## including groups {repo_name} is replaced with just name of repo
156 156
157 157 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
158 158
159 159 ## prefix to add to link to indicate it's an url
160 160 ## #314 will be replaced by <issue_prefix><id>
161 161
162 162 issue_prefix = #
163 163
164 164 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
165 165 ## multiple patterns, to other issues server, wiki or others
166 166 ## below an example how to create a wiki pattern
167 167 # #wiki-some-id -> https://mywiki.com/some-id
168 168
169 169 #issue_pat_wiki = (?:wiki-)(.+)
170 170 #issue_server_link_wiki = https://mywiki.com/{id}
171 171 #issue_prefix_wiki = WIKI-
172 172
173 173
174 174 ## instance-id prefix
175 175 ## a prefix key for this instance used for cache invalidation when running
176 176 ## multiple instances of rhodecode, make sure it's globally unique for
177 177 ## all running rhodecode instances. Leave empty if you don't use it
178 178 instance_id =
179 179
180 180 ## alternative return HTTP header for failed authentication. Default HTTP
181 181 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
182 182 ## handling that. Set this variable to 403 to return HTTPForbidden
183 183 auth_ret_code =
184 184
185 185 ## locking return code. When repository is locked return this HTTP code. 2XX
186 186 ## codes don't break the transactions while 4XX codes do
187 187 lock_ret_code = 423
188 188
189 189
190 190 ####################################
191 191 ### CELERY CONFIG ####
192 192 ####################################
193 193 use_celery = false
194 194 broker.host = localhost
195 195 broker.vhost = rabbitmqhost
196 196 broker.port = 5672
197 197 broker.user = rabbitmq
198 198 broker.password = qweqwe
199 199
200 200 celery.imports = rhodecode.lib.celerylib.tasks
201 201
202 202 celery.result.backend = amqp
203 203 celery.result.dburi = amqp://
204 204 celery.result.serialier = json
205 205
206 206 #celery.send.task.error.emails = true
207 207 #celery.amqp.task.result.expires = 18000
208 208
209 209 celeryd.concurrency = 2
210 210 #celeryd.log.file = celeryd.log
211 211 celeryd.log.level = debug
212 212 celeryd.max.tasks.per.child = 1
213 213
214 214 ## tasks will never be sent to the queue, but executed locally instead.
215 215 celery.always.eager = false
216 216
217 217 ####################################
218 218 ### BEAKER CACHE ####
219 219 ####################################
220 220 beaker.cache.data_dir=/tmp/rc/data/cache/data
221 221 beaker.cache.lock_dir=/tmp/rc/data/cache/lock
222 222
223 223 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
224 224
225 225 beaker.cache.super_short_term.type=memory
226 226 beaker.cache.super_short_term.expire=1
227 227 beaker.cache.super_short_term.key_length = 256
228 228
229 229 beaker.cache.short_term.type=memory
230 230 beaker.cache.short_term.expire=60
231 231 beaker.cache.short_term.key_length = 256
232 232
233 233 beaker.cache.long_term.type=memory
234 234 beaker.cache.long_term.expire=36000
235 235 beaker.cache.long_term.key_length = 256
236 236
237 237 beaker.cache.sql_cache_short.type=memory
238 238 beaker.cache.sql_cache_short.expire=1
239 239 beaker.cache.sql_cache_short.key_length = 256
240 240
241 241 beaker.cache.sql_cache_med.type=memory
242 242 beaker.cache.sql_cache_med.expire=360
243 243 beaker.cache.sql_cache_med.key_length = 256
244 244
245 245 beaker.cache.sql_cache_long.type=file
246 246 beaker.cache.sql_cache_long.expire=3600
247 247 beaker.cache.sql_cache_long.key_length = 256
248 248
249 249 ####################################
250 250 ### BEAKER SESSION ####
251 251 ####################################
252 252 ## Type of storage used for the session, current types are
253 253 ## dbm, file, memcached, database, and memory.
254 254 ## The storage uses the Container API
255 255 ## that is also used by the cache system.
256 256
257 257 ## db session ##
258 258 #beaker.session.type = ext:database
259 259 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
260 260 #beaker.session.table_name = db_session
261 261
262 262 ## encrypted cookie client side session, good for many instances ##
263 263 #beaker.session.type = cookie
264 264
265 265 ## file based cookies (default) ##
266 266 #beaker.session.type = file
267 267
268 268
269 269 beaker.session.key = rhodecode
270 270 ## secure cookie requires AES python libraries
271 271 #beaker.session.encrypt_key = <key_for_encryption>
272 272 #beaker.session.validate_key = <validation_key>
273 273
274 274 ## sets session as invalid if it haven't been accessed for given amount of time
275 275 beaker.session.timeout = 3600
276 276 beaker.session.httponly = true
277 277 #beaker.session.cookie_path = /<your-prefix>
278 278
279 279 ## uncomment for https secure cookie
280 280 beaker.session.secure = false
281 281
282 282 ## auto save the session to not to use .save()
283 283 beaker.session.auto = False
284 284
285 285 ## default cookie expiration time in seconds `true` expire at browser close ##
286 286 #beaker.session.cookie_expires = 3600
287 287
288 288
289 289 ############################
290 290 ## ERROR HANDLING SYSTEMS ##
291 291 ############################
292 292
293 293 ####################
294 294 ### [errormator] ###
295 295 ####################
296 296
297 297 ## Errormator is tailored to work with RhodeCode, see
298 298 ## http://errormator.com for details how to obtain an account
299 299 ## you must install python package `errormator_client` to make it work
300 300
301 301 ## errormator enabled
302 302 errormator = false
303 303
304 304 errormator.server_url = https://api.errormator.com
305 305 errormator.api_key = YOUR_API_KEY
306 306
307 307 ## TWEAK AMOUNT OF INFO SENT HERE
308 308
309 309 ## enables 404 error logging (default False)
310 310 errormator.report_404 = false
311 311
312 312 ## time in seconds after request is considered being slow (default 1)
313 313 errormator.slow_request_time = 1
314 314
315 315 ## record slow requests in application
316 316 ## (needs to be enabled for slow datastore recording and time tracking)
317 317 errormator.slow_requests = true
318 318
319 319 ## enable hooking to application loggers
320 320 # errormator.logging = true
321 321
322 322 ## minimum log level for log capture
323 323 # errormator.logging.level = WARNING
324 324
325 325 ## send logs only from erroneous/slow requests
326 326 ## (saves API quota for intensive logging)
327 327 errormator.logging_on_error = false
328 328
329 329 ## list of additonal keywords that should be grabbed from environ object
330 330 ## can be string with comma separated list of words in lowercase
331 331 ## (by default client will always send following info:
332 332 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
333 333 ## start with HTTP* this list be extended with additional keywords here
334 334 errormator.environ_keys_whitelist =
335 335
336 336
337 337 ## list of keywords that should be blanked from request object
338 338 ## can be string with comma separated list of words in lowercase
339 339 ## (by default client will always blank keys that contain following words
340 340 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
341 341 ## this list be extended with additional keywords set here
342 342 errormator.request_keys_blacklist =
343 343
344 344
345 345 ## list of namespaces that should be ignores when gathering log entries
346 346 ## can be string with comma separated list of namespaces
347 347 ## (by default the client ignores own entries: errormator_client.client)
348 348 errormator.log_namespace_blacklist =
349 349
350 350
351 351 ################
352 352 ### [sentry] ###
353 353 ################
354 354
355 355 ## sentry is a alternative open source error aggregator
356 356 ## you must install python packages `sentry` and `raven` to enable
357 357
358 358 sentry.dsn = YOUR_DNS
359 359 sentry.servers =
360 360 sentry.name =
361 361 sentry.key =
362 362 sentry.public_key =
363 363 sentry.secret_key =
364 364 sentry.project =
365 365 sentry.site =
366 366 sentry.include_paths =
367 367 sentry.exclude_paths =
368 368
369 369
370 370 ################################################################################
371 371 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
372 372 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
373 373 ## execute malicious code after an exception is raised. ##
374 374 ################################################################################
375 375 set debug = false
376 376
377 377 ##################################
378 378 ### LOGVIEW CONFIG ###
379 379 ##################################
380 380 logview.sqlalchemy = #faa
381 381 logview.pylons.templating = #bfb
382 382 logview.pylons.util = #eee
383 383
384 384 #########################################################
385 385 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
386 386 #########################################################
387 387 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.sqlite
388 388 #sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode_test
389 389 #sqlalchemy.db1.url = mysql://root:qwe@localhost/rhodecode_test
390 390 sqlalchemy.db1.echo = false
391 391 sqlalchemy.db1.pool_recycle = 3600
392 392 sqlalchemy.db1.convert_unicode = true
393 393
394 394 ################################
395 395 ### LOGGING CONFIGURATION ####
396 396 ################################
397 397 [loggers]
398 398 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
399 399
400 400 [handlers]
401 401 keys = console, console_sql
402 402
403 403 [formatters]
404 404 keys = generic, color_formatter, color_formatter_sql
405 405
406 406 #############
407 407 ## LOGGERS ##
408 408 #############
409 409 [logger_root]
410 410 level = DEBUG
411 411 handlers = console
412 412
413 413 [logger_routes]
414 414 level = DEBUG
415 415 handlers =
416 416 qualname = routes.middleware
417 417 ## "level = DEBUG" logs the route matched and routing variables.
418 418 propagate = 1
419 419
420 420 [logger_beaker]
421 421 level = DEBUG
422 422 handlers =
423 423 qualname = beaker.container
424 424 propagate = 1
425 425
426 426 [logger_templates]
427 427 level = INFO
428 428 handlers =
429 429 qualname = pylons.templating
430 430 propagate = 1
431 431
432 432 [logger_rhodecode]
433 433 level = DEBUG
434 434 handlers =
435 435 qualname = rhodecode
436 436 propagate = 1
437 437
438 438 [logger_sqlalchemy]
439 439 level = ERROR
440 440 handlers = console
441 441 qualname = sqlalchemy.engine
442 442 propagate = 0
443 443
444 444 [logger_whoosh_indexer]
445 445 level = DEBUG
446 446 handlers =
447 447 qualname = whoosh_indexer
448 448 propagate = 1
449 449
450 450 ##############
451 451 ## HANDLERS ##
452 452 ##############
453 453
454 454 [handler_console]
455 455 class = StreamHandler
456 456 args = (sys.stderr,)
457 457 level = NOTSET
458 458 formatter = generic
459 459
460 460 [handler_console_sql]
461 461 class = StreamHandler
462 462 args = (sys.stderr,)
463 463 level = WARN
464 464 formatter = generic
465 465
466 466 ################
467 467 ## FORMATTERS ##
468 468 ################
469 469
470 470 [formatter_generic]
471 471 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
472 472 datefmt = %Y-%m-%d %H:%M:%S
473 473
474 474 [formatter_color_formatter]
475 475 class=rhodecode.lib.colored_formatter.ColorFormatter
476 476 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
477 477 datefmt = %Y-%m-%d %H:%M:%S
478 478
479 479 [formatter_color_formatter_sql]
480 480 class=rhodecode.lib.colored_formatter.ColorFormatterSql
481 481 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
482 482 datefmt = %Y-%m-%d %H:%M:%S
General Comments 0
You need to be logged in to leave comments. Login now