##// END OF EJS Templates
#518 multiple issues patterns...
marcink -
r2866:736678a8 beta
parent child Browse files
Show More
@@ -1,28 +1,29 b''
1 List of contributors to RhodeCode project:
1 List of contributors to RhodeCode project:
2 Marcin Kuźmiński <marcin@python-works.com>
2 Marcin Kuźmiński <marcin@python-works.com>
3 Lukasz Balcerzak <lukaszbalcerzak@gmail.com>
3 Lukasz Balcerzak <lukaszbalcerzak@gmail.com>
4 Jason Harris <jason@jasonfharris.com>
4 Jason Harris <jason@jasonfharris.com>
5 Thayne Harbaugh <thayne@fusionio.com>
5 Thayne Harbaugh <thayne@fusionio.com>
6 cejones <>
6 cejones <>
7 Thomas Waldmann <tw-public@gmx.de>
7 Thomas Waldmann <tw-public@gmx.de>
8 Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>
8 Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>
9 Dmitri Kuznetsov <>
9 Dmitri Kuznetsov <>
10 Jared Bunting <jared.bunting@peachjean.com>
10 Jared Bunting <jared.bunting@peachjean.com>
11 Steve Romanow <slestak989@gmail.com>
11 Steve Romanow <slestak989@gmail.com>
12 Augosto Hermann <augusto.herrmann@planejamento.gov.br>
12 Augosto Hermann <augusto.herrmann@planejamento.gov.br>
13 Ankit Solanki <ankit.solanki@gmail.com>
13 Ankit Solanki <ankit.solanki@gmail.com>
14 Liad Shani <liadff@gmail.com>
14 Liad Shani <liadff@gmail.com>
15 Les Peabody <lpeabody@gmail.com>
15 Les Peabody <lpeabody@gmail.com>
16 Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>
16 Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>
17 Matt Zuba <matt.zuba@goodwillaz.org>
17 Matt Zuba <matt.zuba@goodwillaz.org>
18 Aras Pranckevicius <aras@unity3d.com>
18 Aras Pranckevicius <aras@unity3d.com>
19 Tony Bussieres <t.bussieres@gmail.com>
19 Tony Bussieres <t.bussieres@gmail.com>
20 Erwin Kroon <e.kroon@smartmetersolutions.nl>
20 Erwin Kroon <e.kroon@smartmetersolutions.nl>
21 nansenat16 <nansenat16@null.tw>
21 nansenat16 <nansenat16@null.tw>
22 Vincent Duvert <vincent@duvert.net>
22 Vincent Duvert <vincent@duvert.net>
23 Takumi IINO <trot.thunder@gmail.com>
23 Takumi IINO <trot.thunder@gmail.com>
24 Indra Talip <indra.talip@gmail.com>
24 Indra Talip <indra.talip@gmail.com>
25 James Rhodes <jrhodes@redpointsoftware.com.au>
25 James Rhodes <jrhodes@redpointsoftware.com.au>
26 Dominik Ruf <dominikruf@gmail.com>
26 Dominik Ruf <dominikruf@gmail.com>
27 xpol <xpolife@gmail.com>
27 xpol <xpolife@gmail.com>
28 Vincent Caron <vcaron@bearstech.com>
28 Vincent Caron <vcaron@bearstech.com>
29 Zachary Auclair <zach101@gmail.com> No newline at end of file
@@ -1,331 +1,341 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20 #email_prefix = [RhodeCode]
20 #email_prefix = [RhodeCode]
21
21
22 #smtp_server = mail.server.com
22 #smtp_server = mail.server.com
23 #smtp_username =
23 #smtp_username =
24 #smtp_password =
24 #smtp_password =
25 #smtp_port =
25 #smtp_port =
26 #smtp_use_tls = false
26 #smtp_use_tls = false
27 #smtp_use_ssl = true
27 #smtp_use_ssl = true
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 #smtp_auth =
29 #smtp_auth =
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 #threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 #threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 #use_threadpool = true
39 #use_threadpool = true
40
40
41 #use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 use = egg:waitress#main
43 host = 0.0.0.0
43 host = 0.0.0.0
44 port = 5000
44 port = 5000
45
45
46 [filter:proxy-prefix]
46 [filter:proxy-prefix]
47 # prefix middleware for rc
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
49 prefix = /<your-prefix>
50
50
51 [app:main]
51 [app:main]
52 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
53 #filter-with = proxy-prefix
54 full_stack = true
54 full_stack = true
55 static_files = true
55 static_files = true
56 # Optional Languages
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
58 lang = en
58 lang = en
59 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
60 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
61 app_instance_uuid = rc-develop
61 app_instance_uuid = rc-develop
62 cut_off_limit = 256000
62 cut_off_limit = 256000
63 force_https = false
63 force_https = false
64 commit_parse_limit = 25
64 commit_parse_limit = 25
65 use_gravatar = true
65 use_gravatar = true
66
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
68 ## the following parts of the URL will be replaced
69 ## {email} user email
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
71 ## {size} size of the image that is expected from the server application
72 ## {scheme} http/https from RhodeCode server
72 ## {scheme} http/https from RhodeCode server
73 ## {netloc} network location from RhodeCode server
73 ## {netloc} network location from RhodeCode server
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
76
76
77 container_auth_enabled = false
77 container_auth_enabled = false
78 proxypass_auth_enabled = false
78 proxypass_auth_enabled = false
79 default_encoding = utf8
79 default_encoding = utf8
80
80
81 ## overwrite schema of clone url
81 ## overwrite schema of clone url
82 ## available vars:
82 ## available vars:
83 ## scheme - http/https
83 ## scheme - http/https
84 ## user - current user
84 ## user - current user
85 ## pass - password
85 ## pass - password
86 ## netloc - network location
86 ## netloc - network location
87 ## path - usually repo_name
87 ## path - usually repo_name
88
88
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
90
90
91 ## issue tracking mapping for commits messages
91 ## issue tracking mapping for commits messages
92 ## comment out issue_pat, issue_server, issue_prefix to enable
92 ## comment out issue_pat, issue_server, issue_prefix to enable
93
93
94 ## pattern to get the issues from commit messages
94 ## pattern to get the issues from commit messages
95 ## default one used here is #<numbers> with a regex passive group for `#`
95 ## default one used here is #<numbers> with a regex passive group for `#`
96 ## {id} will be all groups matched from this pattern
96 ## {id} will be all groups matched from this pattern
97
97
98 issue_pat = (?:\s*#)(\d+)
98 issue_pat = (?:\s*#)(\d+)
99
99
100 ## server url to the issue, each {id} will be replaced with match
100 ## server url to the issue, each {id} will be replaced with match
101 ## fetched from the regex and {repo} is replaced with full repository name
101 ## fetched from the regex and {repo} is replaced with full repository name
102 ## including groups {repo_name} is replaced with just name of repo
102 ## including groups {repo_name} is replaced with just name of repo
103
103
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
105
105
106 ## prefix to add to link to indicate it's an url
106 ## prefix to add to link to indicate it's an url
107 ## #314 will be replaced by <issue_prefix><id>
107 ## #314 will be replaced by <issue_prefix><id>
108
108
109 issue_prefix = #
109 issue_prefix = #
110
110
111 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
112 ## multiple patterns, to other issues server, wiki or others
113 ## below an example how to create a wiki pattern
114 # #wiki-some-id -> https://mywiki.com/some-id
115
116 #issue_pat_wiki = (?:wiki-)(.+)
117 #issue_server_link_wiki = https://mywiki.com/{id}
118 #issue_prefix_wiki = WIKI-
119
120
111 ## instance-id prefix
121 ## instance-id prefix
112 ## a prefix key for this instance used for cache invalidation when running
122 ## a prefix key for this instance used for cache invalidation when running
113 ## multiple instances of rhodecode, make sure it's globally unique for
123 ## multiple instances of rhodecode, make sure it's globally unique for
114 ## all running rhodecode instances. Leave empty if you don't use it
124 ## all running rhodecode instances. Leave empty if you don't use it
115 instance_id =
125 instance_id =
116
126
117 ## alternative return HTTP header for failed authentication. Default HTTP
127 ## alternative return HTTP header for failed authentication. Default HTTP
118 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
128 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
119 ## handling that. Set this variable to 403 to return HTTPForbidden
129 ## handling that. Set this variable to 403 to return HTTPForbidden
120 auth_ret_code =
130 auth_ret_code =
121
131
122 ####################################
132 ####################################
123 ### CELERY CONFIG ####
133 ### CELERY CONFIG ####
124 ####################################
134 ####################################
125 use_celery = false
135 use_celery = false
126 broker.host = localhost
136 broker.host = localhost
127 broker.vhost = rabbitmqhost
137 broker.vhost = rabbitmqhost
128 broker.port = 5672
138 broker.port = 5672
129 broker.user = rabbitmq
139 broker.user = rabbitmq
130 broker.password = qweqwe
140 broker.password = qweqwe
131
141
132 celery.imports = rhodecode.lib.celerylib.tasks
142 celery.imports = rhodecode.lib.celerylib.tasks
133
143
134 celery.result.backend = amqp
144 celery.result.backend = amqp
135 celery.result.dburi = amqp://
145 celery.result.dburi = amqp://
136 celery.result.serialier = json
146 celery.result.serialier = json
137
147
138 #celery.send.task.error.emails = true
148 #celery.send.task.error.emails = true
139 #celery.amqp.task.result.expires = 18000
149 #celery.amqp.task.result.expires = 18000
140
150
141 celeryd.concurrency = 2
151 celeryd.concurrency = 2
142 #celeryd.log.file = celeryd.log
152 #celeryd.log.file = celeryd.log
143 celeryd.log.level = debug
153 celeryd.log.level = debug
144 celeryd.max.tasks.per.child = 1
154 celeryd.max.tasks.per.child = 1
145
155
146 #tasks will never be sent to the queue, but executed locally instead.
156 #tasks will never be sent to the queue, but executed locally instead.
147 celery.always.eager = false
157 celery.always.eager = false
148
158
149 ####################################
159 ####################################
150 ### BEAKER CACHE ####
160 ### BEAKER CACHE ####
151 ####################################
161 ####################################
152 beaker.cache.data_dir=%(here)s/data/cache/data
162 beaker.cache.data_dir=%(here)s/data/cache/data
153 beaker.cache.lock_dir=%(here)s/data/cache/lock
163 beaker.cache.lock_dir=%(here)s/data/cache/lock
154
164
155 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
165 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
156
166
157 beaker.cache.super_short_term.type=memory
167 beaker.cache.super_short_term.type=memory
158 beaker.cache.super_short_term.expire=10
168 beaker.cache.super_short_term.expire=10
159 beaker.cache.super_short_term.key_length = 256
169 beaker.cache.super_short_term.key_length = 256
160
170
161 beaker.cache.short_term.type=memory
171 beaker.cache.short_term.type=memory
162 beaker.cache.short_term.expire=60
172 beaker.cache.short_term.expire=60
163 beaker.cache.short_term.key_length = 256
173 beaker.cache.short_term.key_length = 256
164
174
165 beaker.cache.long_term.type=memory
175 beaker.cache.long_term.type=memory
166 beaker.cache.long_term.expire=36000
176 beaker.cache.long_term.expire=36000
167 beaker.cache.long_term.key_length = 256
177 beaker.cache.long_term.key_length = 256
168
178
169 beaker.cache.sql_cache_short.type=memory
179 beaker.cache.sql_cache_short.type=memory
170 beaker.cache.sql_cache_short.expire=10
180 beaker.cache.sql_cache_short.expire=10
171 beaker.cache.sql_cache_short.key_length = 256
181 beaker.cache.sql_cache_short.key_length = 256
172
182
173 beaker.cache.sql_cache_med.type=memory
183 beaker.cache.sql_cache_med.type=memory
174 beaker.cache.sql_cache_med.expire=360
184 beaker.cache.sql_cache_med.expire=360
175 beaker.cache.sql_cache_med.key_length = 256
185 beaker.cache.sql_cache_med.key_length = 256
176
186
177 beaker.cache.sql_cache_long.type=file
187 beaker.cache.sql_cache_long.type=file
178 beaker.cache.sql_cache_long.expire=3600
188 beaker.cache.sql_cache_long.expire=3600
179 beaker.cache.sql_cache_long.key_length = 256
189 beaker.cache.sql_cache_long.key_length = 256
180
190
181 ####################################
191 ####################################
182 ### BEAKER SESSION ####
192 ### BEAKER SESSION ####
183 ####################################
193 ####################################
184 ## Type of storage used for the session, current types are
194 ## Type of storage used for the session, current types are
185 ## dbm, file, memcached, database, and memory.
195 ## dbm, file, memcached, database, and memory.
186 ## The storage uses the Container API
196 ## The storage uses the Container API
187 ## that is also used by the cache system.
197 ## that is also used by the cache system.
188
198
189 ## db session ##
199 ## db session ##
190 #beaker.session.type = ext:database
200 #beaker.session.type = ext:database
191 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
201 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
192 #beaker.session.table_name = db_session
202 #beaker.session.table_name = db_session
193
203
194 ## encrypted cookie client side session, good for many instances ##
204 ## encrypted cookie client side session, good for many instances ##
195 #beaker.session.type = cookie
205 #beaker.session.type = cookie
196
206
197 ## file based cookies (default) ##
207 ## file based cookies (default) ##
198 #beaker.session.type = file
208 #beaker.session.type = file
199
209
200
210
201 beaker.session.key = rhodecode
211 beaker.session.key = rhodecode
202 ## secure cookie requires AES python libraries ##
212 ## secure cookie requires AES python libraries ##
203 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
213 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
204 #beaker.session.validate_key = 9712sds2212c--zxc123
214 #beaker.session.validate_key = 9712sds2212c--zxc123
205 ## sets session as invalid if it haven't been accessed for given amount of time
215 ## sets session as invalid if it haven't been accessed for given amount of time
206 beaker.session.timeout = 2592000
216 beaker.session.timeout = 2592000
207 beaker.session.httponly = true
217 beaker.session.httponly = true
208 #beaker.session.cookie_path = /<your-prefix>
218 #beaker.session.cookie_path = /<your-prefix>
209
219
210 ## uncomment for https secure cookie ##
220 ## uncomment for https secure cookie ##
211 beaker.session.secure = false
221 beaker.session.secure = false
212
222
213 ## auto save the session to not to use .save() ##
223 ## auto save the session to not to use .save() ##
214 beaker.session.auto = False
224 beaker.session.auto = False
215
225
216 ## default cookie expiration time in seconds `true` expire at browser close ##
226 ## default cookie expiration time in seconds `true` expire at browser close ##
217 #beaker.session.cookie_expires = 3600
227 #beaker.session.cookie_expires = 3600
218
228
219
229
220 ################################################################################
230 ################################################################################
221 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
231 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
222 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
232 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
223 ## execute malicious code after an exception is raised. ##
233 ## execute malicious code after an exception is raised. ##
224 ################################################################################
234 ################################################################################
225 #set debug = false
235 #set debug = false
226
236
227 ##################################
237 ##################################
228 ### LOGVIEW CONFIG ###
238 ### LOGVIEW CONFIG ###
229 ##################################
239 ##################################
230 logview.sqlalchemy = #faa
240 logview.sqlalchemy = #faa
231 logview.pylons.templating = #bfb
241 logview.pylons.templating = #bfb
232 logview.pylons.util = #eee
242 logview.pylons.util = #eee
233
243
234 #########################################################
244 #########################################################
235 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
245 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
236 #########################################################
246 #########################################################
237 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
247 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
238 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
248 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
239 sqlalchemy.db1.echo = false
249 sqlalchemy.db1.echo = false
240 sqlalchemy.db1.pool_recycle = 3600
250 sqlalchemy.db1.pool_recycle = 3600
241 sqlalchemy.db1.convert_unicode = true
251 sqlalchemy.db1.convert_unicode = true
242
252
243 ################################
253 ################################
244 ### LOGGING CONFIGURATION ####
254 ### LOGGING CONFIGURATION ####
245 ################################
255 ################################
246 [loggers]
256 [loggers]
247 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
257 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
248
258
249 [handlers]
259 [handlers]
250 keys = console, console_sql
260 keys = console, console_sql
251
261
252 [formatters]
262 [formatters]
253 keys = generic, color_formatter, color_formatter_sql
263 keys = generic, color_formatter, color_formatter_sql
254
264
255 #############
265 #############
256 ## LOGGERS ##
266 ## LOGGERS ##
257 #############
267 #############
258 [logger_root]
268 [logger_root]
259 level = NOTSET
269 level = NOTSET
260 handlers = console
270 handlers = console
261
271
262 [logger_routes]
272 [logger_routes]
263 level = DEBUG
273 level = DEBUG
264 handlers =
274 handlers =
265 qualname = routes.middleware
275 qualname = routes.middleware
266 # "level = DEBUG" logs the route matched and routing variables.
276 # "level = DEBUG" logs the route matched and routing variables.
267 propagate = 1
277 propagate = 1
268
278
269 [logger_beaker]
279 [logger_beaker]
270 level = DEBUG
280 level = DEBUG
271 handlers =
281 handlers =
272 qualname = beaker.container
282 qualname = beaker.container
273 propagate = 1
283 propagate = 1
274
284
275 [logger_templates]
285 [logger_templates]
276 level = INFO
286 level = INFO
277 handlers =
287 handlers =
278 qualname = pylons.templating
288 qualname = pylons.templating
279 propagate = 1
289 propagate = 1
280
290
281 [logger_rhodecode]
291 [logger_rhodecode]
282 level = DEBUG
292 level = DEBUG
283 handlers =
293 handlers =
284 qualname = rhodecode
294 qualname = rhodecode
285 propagate = 1
295 propagate = 1
286
296
287 [logger_sqlalchemy]
297 [logger_sqlalchemy]
288 level = INFO
298 level = INFO
289 handlers = console_sql
299 handlers = console_sql
290 qualname = sqlalchemy.engine
300 qualname = sqlalchemy.engine
291 propagate = 0
301 propagate = 0
292
302
293 [logger_whoosh_indexer]
303 [logger_whoosh_indexer]
294 level = DEBUG
304 level = DEBUG
295 handlers =
305 handlers =
296 qualname = whoosh_indexer
306 qualname = whoosh_indexer
297 propagate = 1
307 propagate = 1
298
308
299 ##############
309 ##############
300 ## HANDLERS ##
310 ## HANDLERS ##
301 ##############
311 ##############
302
312
303 [handler_console]
313 [handler_console]
304 class = StreamHandler
314 class = StreamHandler
305 args = (sys.stderr,)
315 args = (sys.stderr,)
306 level = DEBUG
316 level = DEBUG
307 formatter = color_formatter
317 formatter = color_formatter
308
318
309 [handler_console_sql]
319 [handler_console_sql]
310 class = StreamHandler
320 class = StreamHandler
311 args = (sys.stderr,)
321 args = (sys.stderr,)
312 level = DEBUG
322 level = DEBUG
313 formatter = color_formatter_sql
323 formatter = color_formatter_sql
314
324
315 ################
325 ################
316 ## FORMATTERS ##
326 ## FORMATTERS ##
317 ################
327 ################
318
328
319 [formatter_generic]
329 [formatter_generic]
320 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
330 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
321 datefmt = %Y-%m-%d %H:%M:%S
331 datefmt = %Y-%m-%d %H:%M:%S
322
332
323 [formatter_color_formatter]
333 [formatter_color_formatter]
324 class=rhodecode.lib.colored_formatter.ColorFormatter
334 class=rhodecode.lib.colored_formatter.ColorFormatter
325 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
335 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
326 datefmt = %Y-%m-%d %H:%M:%S
336 datefmt = %Y-%m-%d %H:%M:%S
327
337
328 [formatter_color_formatter_sql]
338 [formatter_color_formatter_sql]
329 class=rhodecode.lib.colored_formatter.ColorFormatterSql
339 class=rhodecode.lib.colored_formatter.ColorFormatterSql
330 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
340 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
331 datefmt = %Y-%m-%d %H:%M:%S
341 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,789 +1,790 b''
1 .. _changelog:
1 .. _changelog:
2
2
3 =========
3 =========
4 Changelog
4 Changelog
5 =========
5 =========
6
6
7
7
8 1.4.3 (**2012-XX-XX**)
8 1.4.3 (**2012-XX-XX**)
9 ----------------------
9 ----------------------
10
10
11 :status: in-progress
11 :status: in-progress
12 :branch: beta
12 :branch: beta
13
13
14 news
14 news
15 ++++
15 ++++
16
16
17 - #558 Added config file to hooks extra data
17 - #558 Added config file to hooks extra data
18 - bumbped mercurial version to 2.3.1
18 - bumbped mercurial version to 2.3.1
19 - #518 added possibility of specifing multiple patterns for issues
19
20
20 fixes
21 fixes
21 +++++
22 +++++
22
23
23 - fixed #570 explicit users group permissions can overwrite owner permissions
24 - fixed #570 explicit users group permissions can overwrite owner permissions
24
25
25 1.4.2 (**2012-09-12**)
26 1.4.2 (**2012-09-12**)
26 ----------------------
27 ----------------------
27
28
28 news
29 news
29 ++++
30 ++++
30
31
31 - added option to menu to quick lock/unlock repository for users that have
32 - added option to menu to quick lock/unlock repository for users that have
32 write access to
33 write access to
33 - Implemented permissions for writing to repo
34 - Implemented permissions for writing to repo
34 groups. Now only write access to group allows to create a repostiory
35 groups. Now only write access to group allows to create a repostiory
35 within that group
36 within that group
36 - #565 Add support for {netloc} and {scheme} to alternative_gravatar_url
37 - #565 Add support for {netloc} and {scheme} to alternative_gravatar_url
37 - updated translation for zh_CN
38 - updated translation for zh_CN
38
39
39 fixes
40 fixes
40 +++++
41 +++++
41
42
42 - fixed visual permissions check on repos groups inside groups
43 - fixed visual permissions check on repos groups inside groups
43 - fixed issues with non-ascii search terms in search, and indexers
44 - fixed issues with non-ascii search terms in search, and indexers
44 - fixed parsing of page number in GET parameters
45 - fixed parsing of page number in GET parameters
45 - fixed issues with generating pull-request overview for repos with
46 - fixed issues with generating pull-request overview for repos with
46 bookmarks and tags, also preview doesn't loose chosen revision from
47 bookmarks and tags, also preview doesn't loose chosen revision from
47 select dropdown
48 select dropdown
48
49
49 1.4.1 (**2012-09-07**)
50 1.4.1 (**2012-09-07**)
50 ----------------------
51 ----------------------
51
52
52 news
53 news
53 ++++
54 ++++
54
55
55 - always put a comment about code-review status change even if user send
56 - always put a comment about code-review status change even if user send
56 empty data
57 empty data
57 - modified_on column saves repository update and it's going to be used
58 - modified_on column saves repository update and it's going to be used
58 later for light version of main page ref #500
59 later for light version of main page ref #500
59 - pull request notifications send much nicer emails with details about pull
60 - pull request notifications send much nicer emails with details about pull
60 request
61 request
61 - #551 show breadcrumbs in summary view for repositories inside a group
62 - #551 show breadcrumbs in summary view for repositories inside a group
62
63
63 fixes
64 fixes
64 +++++
65 +++++
65
66
66 - fixed migrations of permissions that can lead to inconsistency.
67 - fixed migrations of permissions that can lead to inconsistency.
67 Some users sent feedback that after upgrading from older versions issues
68 Some users sent feedback that after upgrading from older versions issues
68 with updating default permissions occurred. RhodeCode detects that now and
69 with updating default permissions occurred. RhodeCode detects that now and
69 resets default user permission to initial state if there is a need for that.
70 resets default user permission to initial state if there is a need for that.
70 Also forces users to set the default value for new forking permission.
71 Also forces users to set the default value for new forking permission.
71 - #535 improved apache wsgi example configuration in docs
72 - #535 improved apache wsgi example configuration in docs
72 - fixes #550 mercurial repositories comparision failed when origin repo had
73 - fixes #550 mercurial repositories comparision failed when origin repo had
73 additional not-common changesets
74 additional not-common changesets
74 - fixed status of code-review in preview windows of pull request
75 - fixed status of code-review in preview windows of pull request
75 - git forks were not initialized at bare repos
76 - git forks were not initialized at bare repos
76 - fixes #555 fixes issues with comparing non-related repositories
77 - fixes #555 fixes issues with comparing non-related repositories
77 - fixes #557 follower counter always counts up
78 - fixes #557 follower counter always counts up
78 - fixed issue #560 require push ssl checkbox wasn't shown when option was
79 - fixed issue #560 require push ssl checkbox wasn't shown when option was
79 enabled
80 enabled
80 - fixed #559
81 - fixed #559
81 - fixed issue #559 fixed bug in routing that mapped repo names with <name>_<num> in name as
82 - fixed issue #559 fixed bug in routing that mapped repo names with <name>_<num> in name as
82 if it was a request to url by repository ID
83 if it was a request to url by repository ID
83
84
84 1.4.0 (**2012-09-03**)
85 1.4.0 (**2012-09-03**)
85 ----------------------
86 ----------------------
86
87
87 news
88 news
88 ++++
89 ++++
89
90
90 - new codereview system
91 - new codereview system
91 - email map, allowing users to have multiple email addresses mapped into
92 - email map, allowing users to have multiple email addresses mapped into
92 their accounts
93 their accounts
93 - improved git-hook system. Now all actions for git are logged into journal
94 - improved git-hook system. Now all actions for git are logged into journal
94 including pushed revisions, user and IP address
95 including pushed revisions, user and IP address
95 - changed setup-app into setup-rhodecode and added default options to it.
96 - changed setup-app into setup-rhodecode and added default options to it.
96 - new git repos are created as bare now by default
97 - new git repos are created as bare now by default
97 - #464 added links to groups in permission box
98 - #464 added links to groups in permission box
98 - #465 mentions autocomplete inside comments boxes
99 - #465 mentions autocomplete inside comments boxes
99 - #469 added --update-only option to whoosh to re-index only given list
100 - #469 added --update-only option to whoosh to re-index only given list
100 of repos in index
101 of repos in index
101 - rhodecode-api CLI client
102 - rhodecode-api CLI client
102 - new git http protocol replaced buggy dulwich implementation.
103 - new git http protocol replaced buggy dulwich implementation.
103 Now based on pygrack & gitweb
104 Now based on pygrack & gitweb
104 - Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and
105 - Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and
105 reformated based on user suggestions. Additional rss/atom feeds for user
106 reformated based on user suggestions. Additional rss/atom feeds for user
106 journal
107 journal
107 - various i18n improvements
108 - various i18n improvements
108 - #478 permissions overview for admin in user edit view
109 - #478 permissions overview for admin in user edit view
109 - File view now displays small gravatars off all authors of given file
110 - File view now displays small gravatars off all authors of given file
110 - Implemented landing revisions. Each repository will get landing_rev attribute
111 - Implemented landing revisions. Each repository will get landing_rev attribute
111 that defines 'default' revision/branch for generating readme files
112 that defines 'default' revision/branch for generating readme files
112 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested at
113 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested at
113 earliest possible call.
114 earliest possible call.
114 - Import remote svn repositories to mercurial using hgsubversion.
115 - Import remote svn repositories to mercurial using hgsubversion.
115 - Fixed #508 RhodeCode now has a option to explicitly set forking permissions
116 - Fixed #508 RhodeCode now has a option to explicitly set forking permissions
116 - RhodeCode can use alternative server for generating avatar icons
117 - RhodeCode can use alternative server for generating avatar icons
117 - implemented repositories locking. Pull locks, push unlocks. Also can be done
118 - implemented repositories locking. Pull locks, push unlocks. Also can be done
118 via API calls
119 via API calls
119 - #538 form for permissions can handle multiple users at once
120 - #538 form for permissions can handle multiple users at once
120
121
121 fixes
122 fixes
122 +++++
123 +++++
123
124
124 - improved translations
125 - improved translations
125 - fixes issue #455 Creating an archive generates an exception on Windows
126 - fixes issue #455 Creating an archive generates an exception on Windows
126 - fixes #448 Download ZIP archive keeps file in /tmp open and results
127 - fixes #448 Download ZIP archive keeps file in /tmp open and results
127 in out of disk space
128 in out of disk space
128 - fixes issue #454 Search results under Windows include proceeding
129 - fixes issue #454 Search results under Windows include proceeding
129 backslash
130 backslash
130 - fixed issue #450. Rhodecode no longer will crash when bad revision is
131 - fixed issue #450. Rhodecode no longer will crash when bad revision is
131 present in journal data.
132 present in journal data.
132 - fix for issue #417, git execution was broken on windows for certain
133 - fix for issue #417, git execution was broken on windows for certain
133 commands.
134 commands.
134 - fixed #413. Don't disable .git directory for bare repos on deleting
135 - fixed #413. Don't disable .git directory for bare repos on deleting
135 - fixed issue #459. Changed the way of obtaining logger in reindex task.
136 - fixed issue #459. Changed the way of obtaining logger in reindex task.
136 - fixed #453 added ID field in whoosh SCHEMA that solves the issue of
137 - fixed #453 added ID field in whoosh SCHEMA that solves the issue of
137 reindexing modified files
138 reindexing modified files
138 - fixed #481 rhodecode emails are sent without Date header
139 - fixed #481 rhodecode emails are sent without Date header
139 - fixed #458 wrong count when no repos are present
140 - fixed #458 wrong count when no repos are present
140 - fixed issue #492 missing `\ No newline at end of file` test at the end of
141 - fixed issue #492 missing `\ No newline at end of file` test at the end of
141 new chunk in html diff
142 new chunk in html diff
142 - full text search now works also for commit messages
143 - full text search now works also for commit messages
143
144
144 1.3.6 (**2012-05-17**)
145 1.3.6 (**2012-05-17**)
145 ----------------------
146 ----------------------
146
147
147 news
148 news
148 ++++
149 ++++
149
150
150 - chinese traditional translation
151 - chinese traditional translation
151 - changed setup-app into setup-rhodecode and added arguments for auto-setup
152 - changed setup-app into setup-rhodecode and added arguments for auto-setup
152 mode that doesn't need user interaction
153 mode that doesn't need user interaction
153
154
154 fixes
155 fixes
155 +++++
156 +++++
156
157
157 - fixed no scm found warning
158 - fixed no scm found warning
158 - fixed __future__ import error on rcextensions
159 - fixed __future__ import error on rcextensions
159 - made simplejson required lib for speedup on JSON encoding
160 - made simplejson required lib for speedup on JSON encoding
160 - fixes #449 bad regex could get more than revisions from parsing history
161 - fixes #449 bad regex could get more than revisions from parsing history
161 - don't clear DB session when CELERY_EAGER is turned ON
162 - don't clear DB session when CELERY_EAGER is turned ON
162
163
163 1.3.5 (**2012-05-10**)
164 1.3.5 (**2012-05-10**)
164 ----------------------
165 ----------------------
165
166
166 news
167 news
167 ++++
168 ++++
168
169
169 - use ext_json for json module
170 - use ext_json for json module
170 - unified annotation view with file source view
171 - unified annotation view with file source view
171 - notification improvements, better inbox + css
172 - notification improvements, better inbox + css
172 - #419 don't strip passwords for login forms, make rhodecode
173 - #419 don't strip passwords for login forms, make rhodecode
173 more compatible with LDAP servers
174 more compatible with LDAP servers
174 - Added HTTP_X_FORWARDED_FOR as another method of extracting
175 - Added HTTP_X_FORWARDED_FOR as another method of extracting
175 IP for pull/push logs. - moved all to base controller
176 IP for pull/push logs. - moved all to base controller
176 - #415: Adding comment to changeset causes reload.
177 - #415: Adding comment to changeset causes reload.
177 Comments are now added via ajax and doesn't reload the page
178 Comments are now added via ajax and doesn't reload the page
178 - #374 LDAP config is discarded when LDAP can't be activated
179 - #374 LDAP config is discarded when LDAP can't be activated
179 - limited push/pull operations are now logged for git in the journal
180 - limited push/pull operations are now logged for git in the journal
180 - bumped mercurial to 2.2.X series
181 - bumped mercurial to 2.2.X series
181 - added support for displaying submodules in file-browser
182 - added support for displaying submodules in file-browser
182 - #421 added bookmarks in changelog view
183 - #421 added bookmarks in changelog view
183
184
184 fixes
185 fixes
185 +++++
186 +++++
186
187
187 - fixed dev-version marker for stable when served from source codes
188 - fixed dev-version marker for stable when served from source codes
188 - fixed missing permission checks on show forks page
189 - fixed missing permission checks on show forks page
189 - #418 cast to unicode fixes in notification objects
190 - #418 cast to unicode fixes in notification objects
190 - #426 fixed mention extracting regex
191 - #426 fixed mention extracting regex
191 - fixed remote-pulling for git remotes remopositories
192 - fixed remote-pulling for git remotes remopositories
192 - fixed #434: Error when accessing files or changesets of a git repository
193 - fixed #434: Error when accessing files or changesets of a git repository
193 with submodules
194 with submodules
194 - fixed issue with empty APIKEYS for users after registration ref. #438
195 - fixed issue with empty APIKEYS for users after registration ref. #438
195 - fixed issue with getting README files from git repositories
196 - fixed issue with getting README files from git repositories
196
197
197 1.3.4 (**2012-03-28**)
198 1.3.4 (**2012-03-28**)
198 ----------------------
199 ----------------------
199
200
200 news
201 news
201 ++++
202 ++++
202
203
203 - Whoosh logging is now controlled by the .ini files logging setup
204 - Whoosh logging is now controlled by the .ini files logging setup
204 - added clone-url into edit form on /settings page
205 - added clone-url into edit form on /settings page
205 - added help text into repo add/edit forms
206 - added help text into repo add/edit forms
206 - created rcextensions module with additional mappings (ref #322) and
207 - created rcextensions module with additional mappings (ref #322) and
207 post push/pull/create repo hooks callbacks
208 post push/pull/create repo hooks callbacks
208 - implemented #377 Users view for his own permissions on account page
209 - implemented #377 Users view for his own permissions on account page
209 - #399 added inheritance of permissions for users group on repos groups
210 - #399 added inheritance of permissions for users group on repos groups
210 - #401 repository group is automatically pre-selected when adding repos
211 - #401 repository group is automatically pre-selected when adding repos
211 inside a repository group
212 inside a repository group
212 - added alternative HTTP 403 response when client failed to authenticate. Helps
213 - added alternative HTTP 403 response when client failed to authenticate. Helps
213 solving issues with Mercurial and LDAP
214 solving issues with Mercurial and LDAP
214 - #402 removed group prefix from repository name when listing repositories
215 - #402 removed group prefix from repository name when listing repositories
215 inside a group
216 inside a group
216 - added gravatars into permission view and permissions autocomplete
217 - added gravatars into permission view and permissions autocomplete
217 - #347 when running multiple RhodeCode instances, properly invalidates cache
218 - #347 when running multiple RhodeCode instances, properly invalidates cache
218 for all registered servers
219 for all registered servers
219
220
220 fixes
221 fixes
221 +++++
222 +++++
222
223
223 - fixed #390 cache invalidation problems on repos inside group
224 - fixed #390 cache invalidation problems on repos inside group
224 - fixed #385 clone by ID url was loosing proxy prefix in URL
225 - fixed #385 clone by ID url was loosing proxy prefix in URL
225 - fixed some unicode problems with waitress
226 - fixed some unicode problems with waitress
226 - fixed issue with escaping < and > in changeset commits
227 - fixed issue with escaping < and > in changeset commits
227 - fixed error occurring during recursive group creation in API
228 - fixed error occurring during recursive group creation in API
228 create_repo function
229 create_repo function
229 - fixed #393 py2.5 fixes for routes url generator
230 - fixed #393 py2.5 fixes for routes url generator
230 - fixed #397 Private repository groups shows up before login
231 - fixed #397 Private repository groups shows up before login
231 - fixed #396 fixed problems with revoking users in nested groups
232 - fixed #396 fixed problems with revoking users in nested groups
232 - fixed mysql unicode issues + specified InnoDB as default engine with
233 - fixed mysql unicode issues + specified InnoDB as default engine with
233 utf8 charset
234 utf8 charset
234 - #406 trim long branch/tag names in changelog to not break UI
235 - #406 trim long branch/tag names in changelog to not break UI
235
236
236 1.3.3 (**2012-03-02**)
237 1.3.3 (**2012-03-02**)
237 ----------------------
238 ----------------------
238
239
239 news
240 news
240 ++++
241 ++++
241
242
242
243
243 fixes
244 fixes
244 +++++
245 +++++
245
246
246 - fixed some python2.5 compatibility issues
247 - fixed some python2.5 compatibility issues
247 - fixed issues with removed repos was accidentally added as groups, after
248 - fixed issues with removed repos was accidentally added as groups, after
248 full rescan of paths
249 full rescan of paths
249 - fixes #376 Cannot edit user (using container auth)
250 - fixes #376 Cannot edit user (using container auth)
250 - fixes #378 Invalid image urls on changeset screen with proxy-prefix
251 - fixes #378 Invalid image urls on changeset screen with proxy-prefix
251 configuration
252 configuration
252 - fixed initial sorting of repos inside repo group
253 - fixed initial sorting of repos inside repo group
253 - fixes issue when user tried to resubmit same permission into user/user_groups
254 - fixes issue when user tried to resubmit same permission into user/user_groups
254 - bumped beaker version that fixes #375 leap error bug
255 - bumped beaker version that fixes #375 leap error bug
255 - fixed raw_changeset for git. It was generated with hg patch headers
256 - fixed raw_changeset for git. It was generated with hg patch headers
256 - fixed vcs issue with last_changeset for filenodes
257 - fixed vcs issue with last_changeset for filenodes
257 - fixed missing commit after hook delete
258 - fixed missing commit after hook delete
258 - fixed #372 issues with git operation detection that caused a security issue
259 - fixed #372 issues with git operation detection that caused a security issue
259 for git repos
260 for git repos
260
261
261 1.3.2 (**2012-02-28**)
262 1.3.2 (**2012-02-28**)
262 ----------------------
263 ----------------------
263
264
264 news
265 news
265 ++++
266 ++++
266
267
267
268
268 fixes
269 fixes
269 +++++
270 +++++
270
271
271 - fixed git protocol issues with repos-groups
272 - fixed git protocol issues with repos-groups
272 - fixed git remote repos validator that prevented from cloning remote git repos
273 - fixed git remote repos validator that prevented from cloning remote git repos
273 - fixes #370 ending slashes fixes for repo and groups
274 - fixes #370 ending slashes fixes for repo and groups
274 - fixes #368 improved git-protocol detection to handle other clients
275 - fixes #368 improved git-protocol detection to handle other clients
275 - fixes #366 When Setting Repository Group To Blank Repo Group Wont Be
276 - fixes #366 When Setting Repository Group To Blank Repo Group Wont Be
276 Moved To Root
277 Moved To Root
277 - fixes #371 fixed issues with beaker/sqlalchemy and non-ascii cache keys
278 - fixes #371 fixed issues with beaker/sqlalchemy and non-ascii cache keys
278 - fixed #373 missing cascade drop on user_group_to_perm table
279 - fixed #373 missing cascade drop on user_group_to_perm table
279
280
280 1.3.1 (**2012-02-27**)
281 1.3.1 (**2012-02-27**)
281 ----------------------
282 ----------------------
282
283
283 news
284 news
284 ++++
285 ++++
285
286
286
287
287 fixes
288 fixes
288 +++++
289 +++++
289
290
290 - redirection loop occurs when remember-me wasn't checked during login
291 - redirection loop occurs when remember-me wasn't checked during login
291 - fixes issues with git blob history generation
292 - fixes issues with git blob history generation
292 - don't fetch branch for git in file history dropdown. Causes unneeded slowness
293 - don't fetch branch for git in file history dropdown. Causes unneeded slowness
293
294
294 1.3.0 (**2012-02-26**)
295 1.3.0 (**2012-02-26**)
295 ----------------------
296 ----------------------
296
297
297 news
298 news
298 ++++
299 ++++
299
300
300 - code review, inspired by github code-comments
301 - code review, inspired by github code-comments
301 - #215 rst and markdown README files support
302 - #215 rst and markdown README files support
302 - #252 Container-based and proxy pass-through authentication support
303 - #252 Container-based and proxy pass-through authentication support
303 - #44 branch browser. Filtering of changelog by branches
304 - #44 branch browser. Filtering of changelog by branches
304 - mercurial bookmarks support
305 - mercurial bookmarks support
305 - new hover top menu, optimized to add maximum size for important views
306 - new hover top menu, optimized to add maximum size for important views
306 - configurable clone url template with possibility to specify protocol like
307 - configurable clone url template with possibility to specify protocol like
307 ssh:// or http:// and also manually alter other parts of clone_url.
308 ssh:// or http:// and also manually alter other parts of clone_url.
308 - enabled largefiles extension by default
309 - enabled largefiles extension by default
309 - optimized summary file pages and saved a lot of unused space in them
310 - optimized summary file pages and saved a lot of unused space in them
310 - #239 option to manually mark repository as fork
311 - #239 option to manually mark repository as fork
311 - #320 mapping of commit authors to RhodeCode users
312 - #320 mapping of commit authors to RhodeCode users
312 - #304 hashes are displayed using monospace font
313 - #304 hashes are displayed using monospace font
313 - diff configuration, toggle white lines and context lines
314 - diff configuration, toggle white lines and context lines
314 - #307 configurable diffs, whitespace toggle, increasing context lines
315 - #307 configurable diffs, whitespace toggle, increasing context lines
315 - sorting on branches, tags and bookmarks using YUI datatable
316 - sorting on branches, tags and bookmarks using YUI datatable
316 - improved file filter on files page
317 - improved file filter on files page
317 - implements #330 api method for listing nodes ar particular revision
318 - implements #330 api method for listing nodes ar particular revision
318 - #73 added linking issues in commit messages to chosen issue tracker url
319 - #73 added linking issues in commit messages to chosen issue tracker url
319 based on user defined regular expression
320 based on user defined regular expression
320 - added linking of changesets in commit messages
321 - added linking of changesets in commit messages
321 - new compact changelog with expandable commit messages
322 - new compact changelog with expandable commit messages
322 - firstname and lastname are optional in user creation
323 - firstname and lastname are optional in user creation
323 - #348 added post-create repository hook
324 - #348 added post-create repository hook
324 - #212 global encoding settings is now configurable from .ini files
325 - #212 global encoding settings is now configurable from .ini files
325 - #227 added repository groups permissions
326 - #227 added repository groups permissions
326 - markdown gets codehilite extensions
327 - markdown gets codehilite extensions
327 - new API methods, delete_repositories, grante/revoke permissions for groups
328 - new API methods, delete_repositories, grante/revoke permissions for groups
328 and repos
329 and repos
329
330
330
331
331 fixes
332 fixes
332 +++++
333 +++++
333
334
334 - rewrote dbsession management for atomic operations, and better error handling
335 - rewrote dbsession management for atomic operations, and better error handling
335 - fixed sorting of repo tables
336 - fixed sorting of repo tables
336 - #326 escape of special html entities in diffs
337 - #326 escape of special html entities in diffs
337 - normalized user_name => username in api attributes
338 - normalized user_name => username in api attributes
338 - fixes #298 ldap created users with mixed case emails created conflicts
339 - fixes #298 ldap created users with mixed case emails created conflicts
339 on saving a form
340 on saving a form
340 - fixes issue when owner of a repo couldn't revoke permissions for users
341 - fixes issue when owner of a repo couldn't revoke permissions for users
341 and groups
342 and groups
342 - fixes #271 rare JSON serialization problem with statistics
343 - fixes #271 rare JSON serialization problem with statistics
343 - fixes #337 missing validation check for conflicting names of a group with a
344 - fixes #337 missing validation check for conflicting names of a group with a
344 repositories group
345 repositories group
345 - #340 fixed session problem for mysql and celery tasks
346 - #340 fixed session problem for mysql and celery tasks
346 - fixed #331 RhodeCode mangles repository names if the a repository group
347 - fixed #331 RhodeCode mangles repository names if the a repository group
347 contains the "full path" to the repositories
348 contains the "full path" to the repositories
348 - #355 RhodeCode doesn't store encrypted LDAP passwords
349 - #355 RhodeCode doesn't store encrypted LDAP passwords
349
350
350 1.2.5 (**2012-01-28**)
351 1.2.5 (**2012-01-28**)
351 ----------------------
352 ----------------------
352
353
353 news
354 news
354 ++++
355 ++++
355
356
356 fixes
357 fixes
357 +++++
358 +++++
358
359
359 - #340 Celery complains about MySQL server gone away, added session cleanup
360 - #340 Celery complains about MySQL server gone away, added session cleanup
360 for celery tasks
361 for celery tasks
361 - #341 "scanning for repositories in None" log message during Rescan was missing
362 - #341 "scanning for repositories in None" log message during Rescan was missing
362 a parameter
363 a parameter
363 - fixed creating archives with subrepos. Some hooks were triggered during that
364 - fixed creating archives with subrepos. Some hooks were triggered during that
364 operation leading to crash.
365 operation leading to crash.
365 - fixed missing email in account page.
366 - fixed missing email in account page.
366 - Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes
367 - Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes
367 forking on windows impossible
368 forking on windows impossible
368
369
369 1.2.4 (**2012-01-19**)
370 1.2.4 (**2012-01-19**)
370 ----------------------
371 ----------------------
371
372
372 news
373 news
373 ++++
374 ++++
374
375
375 - RhodeCode is bundled with mercurial series 2.0.X by default, with
376 - RhodeCode is bundled with mercurial series 2.0.X by default, with
376 full support to largefiles extension. Enabled by default in new installations
377 full support to largefiles extension. Enabled by default in new installations
377 - #329 Ability to Add/Remove Groups to/from a Repository via AP
378 - #329 Ability to Add/Remove Groups to/from a Repository via AP
378 - added requires.txt file with requirements
379 - added requires.txt file with requirements
379
380
380 fixes
381 fixes
381 +++++
382 +++++
382
383
383 - fixes db session issues with celery when emailing admins
384 - fixes db session issues with celery when emailing admins
384 - #331 RhodeCode mangles repository names if the a repository group
385 - #331 RhodeCode mangles repository names if the a repository group
385 contains the "full path" to the repositories
386 contains the "full path" to the repositories
386 - #298 Conflicting e-mail addresses for LDAP and RhodeCode users
387 - #298 Conflicting e-mail addresses for LDAP and RhodeCode users
387 - DB session cleanup after hg protocol operations, fixes issues with
388 - DB session cleanup after hg protocol operations, fixes issues with
388 `mysql has gone away` errors
389 `mysql has gone away` errors
389 - #333 doc fixes for get_repo api function
390 - #333 doc fixes for get_repo api function
390 - #271 rare JSON serialization problem with statistics enabled
391 - #271 rare JSON serialization problem with statistics enabled
391 - #337 Fixes issues with validation of repository name conflicting with
392 - #337 Fixes issues with validation of repository name conflicting with
392 a group name. A proper message is now displayed.
393 a group name. A proper message is now displayed.
393 - #292 made ldap_dn in user edit readonly, to get rid of confusion that field
394 - #292 made ldap_dn in user edit readonly, to get rid of confusion that field
394 doesn't work
395 doesn't work
395 - #316 fixes issues with web description in hgrc files
396 - #316 fixes issues with web description in hgrc files
396
397
397 1.2.3 (**2011-11-02**)
398 1.2.3 (**2011-11-02**)
398 ----------------------
399 ----------------------
399
400
400 news
401 news
401 ++++
402 ++++
402
403
403 - added option to manage repos group for non admin users
404 - added option to manage repos group for non admin users
404 - added following API methods for get_users, create_user, get_users_groups,
405 - added following API methods for get_users, create_user, get_users_groups,
405 get_users_group, create_users_group, add_user_to_users_groups, get_repos,
406 get_users_group, create_users_group, add_user_to_users_groups, get_repos,
406 get_repo, create_repo, add_user_to_repo
407 get_repo, create_repo, add_user_to_repo
407 - implements #237 added password confirmation for my account
408 - implements #237 added password confirmation for my account
408 and admin edit user.
409 and admin edit user.
409 - implements #291 email notification for global events are now sent to all
410 - implements #291 email notification for global events are now sent to all
410 administrator users, and global config email.
411 administrator users, and global config email.
411
412
412 fixes
413 fixes
413 +++++
414 +++++
414
415
415 - added option for passing auth method for smtp mailer
416 - added option for passing auth method for smtp mailer
416 - #276 issue with adding a single user with id>10 to usergroups
417 - #276 issue with adding a single user with id>10 to usergroups
417 - #277 fixes windows LDAP settings in which missing values breaks the ldap auth
418 - #277 fixes windows LDAP settings in which missing values breaks the ldap auth
418 - #288 fixes managing of repos in a group for non admin user
419 - #288 fixes managing of repos in a group for non admin user
419
420
420 1.2.2 (**2011-10-17**)
421 1.2.2 (**2011-10-17**)
421 ----------------------
422 ----------------------
422
423
423 news
424 news
424 ++++
425 ++++
425
426
426 - #226 repo groups are available by path instead of numerical id
427 - #226 repo groups are available by path instead of numerical id
427
428
428 fixes
429 fixes
429 +++++
430 +++++
430
431
431 - #259 Groups with the same name but with different parent group
432 - #259 Groups with the same name but with different parent group
432 - #260 Put repo in group, then move group to another group -> repo becomes unavailable
433 - #260 Put repo in group, then move group to another group -> repo becomes unavailable
433 - #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems)
434 - #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems)
434 - #265 ldap save fails sometimes on converting attributes to booleans,
435 - #265 ldap save fails sometimes on converting attributes to booleans,
435 added getter and setter into model that will prevent from this on db model level
436 added getter and setter into model that will prevent from this on db model level
436 - fixed problems with timestamps issues #251 and #213
437 - fixed problems with timestamps issues #251 and #213
437 - fixes #266 RhodeCode allows to create repo with the same name and in
438 - fixes #266 RhodeCode allows to create repo with the same name and in
438 the same parent as group
439 the same parent as group
439 - fixes #245 Rescan of the repositories on Windows
440 - fixes #245 Rescan of the repositories on Windows
440 - fixes #248 cannot edit repos inside a group on windows
441 - fixes #248 cannot edit repos inside a group on windows
441 - fixes #219 forking problems on windows
442 - fixes #219 forking problems on windows
442
443
443 1.2.1 (**2011-10-08**)
444 1.2.1 (**2011-10-08**)
444 ----------------------
445 ----------------------
445
446
446 news
447 news
447 ++++
448 ++++
448
449
449
450
450 fixes
451 fixes
451 +++++
452 +++++
452
453
453 - fixed problems with basic auth and push problems
454 - fixed problems with basic auth and push problems
454 - gui fixes
455 - gui fixes
455 - fixed logger
456 - fixed logger
456
457
457 1.2.0 (**2011-10-07**)
458 1.2.0 (**2011-10-07**)
458 ----------------------
459 ----------------------
459
460
460 news
461 news
461 ++++
462 ++++
462
463
463 - implemented #47 repository groups
464 - implemented #47 repository groups
464 - implemented #89 Can setup google analytics code from settings menu
465 - implemented #89 Can setup google analytics code from settings menu
465 - implemented #91 added nicer looking archive urls with more download options
466 - implemented #91 added nicer looking archive urls with more download options
466 like tags, branches
467 like tags, branches
467 - implemented #44 into file browsing, and added follow branch option
468 - implemented #44 into file browsing, and added follow branch option
468 - implemented #84 downloads can be enabled/disabled for each repository
469 - implemented #84 downloads can be enabled/disabled for each repository
469 - anonymous repository can be cloned without having to pass default:default
470 - anonymous repository can be cloned without having to pass default:default
470 into clone url
471 into clone url
471 - fixed #90 whoosh indexer can index chooses repositories passed in command
472 - fixed #90 whoosh indexer can index chooses repositories passed in command
472 line
473 line
473 - extended journal with day aggregates and paging
474 - extended journal with day aggregates and paging
474 - implemented #107 source code lines highlight ranges
475 - implemented #107 source code lines highlight ranges
475 - implemented #93 customizable changelog on combined revision ranges -
476 - implemented #93 customizable changelog on combined revision ranges -
476 equivalent of githubs compare view
477 equivalent of githubs compare view
477 - implemented #108 extended and more powerful LDAP configuration
478 - implemented #108 extended and more powerful LDAP configuration
478 - implemented #56 users groups
479 - implemented #56 users groups
479 - major code rewrites optimized codes for speed and memory usage
480 - major code rewrites optimized codes for speed and memory usage
480 - raw and diff downloads are now in git format
481 - raw and diff downloads are now in git format
481 - setup command checks for write access to given path
482 - setup command checks for write access to given path
482 - fixed many issues with international characters and unicode. It uses utf8
483 - fixed many issues with international characters and unicode. It uses utf8
483 decode with replace to provide less errors even with non utf8 encoded strings
484 decode with replace to provide less errors even with non utf8 encoded strings
484 - #125 added API KEY access to feeds
485 - #125 added API KEY access to feeds
485 - #109 Repository can be created from external Mercurial link (aka. remote
486 - #109 Repository can be created from external Mercurial link (aka. remote
486 repository, and manually updated (via pull) from admin panel
487 repository, and manually updated (via pull) from admin panel
487 - beta git support - push/pull server + basic view for git repos
488 - beta git support - push/pull server + basic view for git repos
488 - added followers page and forks page
489 - added followers page and forks page
489 - server side file creation (with binary file upload interface)
490 - server side file creation (with binary file upload interface)
490 and edition with commits powered by codemirror
491 and edition with commits powered by codemirror
491 - #111 file browser file finder, quick lookup files on whole file tree
492 - #111 file browser file finder, quick lookup files on whole file tree
492 - added quick login sliding menu into main page
493 - added quick login sliding menu into main page
493 - changelog uses lazy loading of affected files details, in some scenarios
494 - changelog uses lazy loading of affected files details, in some scenarios
494 this can improve speed of changelog page dramatically especially for
495 this can improve speed of changelog page dramatically especially for
495 larger repositories.
496 larger repositories.
496 - implements #214 added support for downloading subrepos in download menu.
497 - implements #214 added support for downloading subrepos in download menu.
497 - Added basic API for direct operations on rhodecode via JSON
498 - Added basic API for direct operations on rhodecode via JSON
498 - Implemented advanced hook management
499 - Implemented advanced hook management
499
500
500 fixes
501 fixes
501 +++++
502 +++++
502
503
503 - fixed file browser bug, when switching into given form revision the url was
504 - fixed file browser bug, when switching into given form revision the url was
504 not changing
505 not changing
505 - fixed propagation to error controller on simplehg and simplegit middlewares
506 - fixed propagation to error controller on simplehg and simplegit middlewares
506 - fixed error when trying to make a download on empty repository
507 - fixed error when trying to make a download on empty repository
507 - fixed problem with '[' chars in commit messages in journal
508 - fixed problem with '[' chars in commit messages in journal
508 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
509 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
509 - journal fork fixes
510 - journal fork fixes
510 - removed issue with space inside renamed repository after deletion
511 - removed issue with space inside renamed repository after deletion
511 - fixed strange issue on formencode imports
512 - fixed strange issue on formencode imports
512 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
513 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
513 - #150 fixes for errors on repositories mapped in db but corrupted in
514 - #150 fixes for errors on repositories mapped in db but corrupted in
514 filesystem
515 filesystem
515 - fixed problem with ascendant characters in realm #181
516 - fixed problem with ascendant characters in realm #181
516 - fixed problem with sqlite file based database connection pool
517 - fixed problem with sqlite file based database connection pool
517 - whoosh indexer and code stats share the same dynamic extensions map
518 - whoosh indexer and code stats share the same dynamic extensions map
518 - fixes #188 - relationship delete of repo_to_perm entry on user removal
519 - fixes #188 - relationship delete of repo_to_perm entry on user removal
519 - fixes issue #189 Trending source files shows "show more" when no more exist
520 - fixes issue #189 Trending source files shows "show more" when no more exist
520 - fixes issue #197 Relative paths for pidlocks
521 - fixes issue #197 Relative paths for pidlocks
521 - fixes issue #198 password will require only 3 chars now for login form
522 - fixes issue #198 password will require only 3 chars now for login form
522 - fixes issue #199 wrong redirection for non admin users after creating a repository
523 - fixes issue #199 wrong redirection for non admin users after creating a repository
523 - fixes issues #202, bad db constraint made impossible to attach same group
524 - fixes issues #202, bad db constraint made impossible to attach same group
524 more than one time. Affects only mysql/postgres
525 more than one time. Affects only mysql/postgres
525 - fixes #218 os.kill patch for windows was missing sig param
526 - fixes #218 os.kill patch for windows was missing sig param
526 - improved rendering of dag (they are not trimmed anymore when number of
527 - improved rendering of dag (they are not trimmed anymore when number of
527 heads exceeds 5)
528 heads exceeds 5)
528
529
529 1.1.8 (**2011-04-12**)
530 1.1.8 (**2011-04-12**)
530 ----------------------
531 ----------------------
531
532
532 news
533 news
533 ++++
534 ++++
534
535
535 - improved windows support
536 - improved windows support
536
537
537 fixes
538 fixes
538 +++++
539 +++++
539
540
540 - fixed #140 freeze of python dateutil library, since new version is python2.x
541 - fixed #140 freeze of python dateutil library, since new version is python2.x
541 incompatible
542 incompatible
542 - setup-app will check for write permission in given path
543 - setup-app will check for write permission in given path
543 - cleaned up license info issue #149
544 - cleaned up license info issue #149
544 - fixes for issues #137,#116 and problems with unicode and accented characters.
545 - fixes for issues #137,#116 and problems with unicode and accented characters.
545 - fixes crashes on gravatar, when passed in email as unicode
546 - fixes crashes on gravatar, when passed in email as unicode
546 - fixed tooltip flickering problems
547 - fixed tooltip flickering problems
547 - fixed came_from redirection on windows
548 - fixed came_from redirection on windows
548 - fixed logging modules, and sql formatters
549 - fixed logging modules, and sql formatters
549 - windows fixes for os.kill issue #133
550 - windows fixes for os.kill issue #133
550 - fixes path splitting for windows issues #148
551 - fixes path splitting for windows issues #148
551 - fixed issue #143 wrong import on migration to 1.1.X
552 - fixed issue #143 wrong import on migration to 1.1.X
552 - fixed problems with displaying binary files, thanks to Thomas Waldmann
553 - fixed problems with displaying binary files, thanks to Thomas Waldmann
553 - removed name from archive files since it's breaking ui for long repo names
554 - removed name from archive files since it's breaking ui for long repo names
554 - fixed issue with archive headers sent to browser, thanks to Thomas Waldmann
555 - fixed issue with archive headers sent to browser, thanks to Thomas Waldmann
555 - fixed compatibility for 1024px displays, and larger dpi settings, thanks to
556 - fixed compatibility for 1024px displays, and larger dpi settings, thanks to
556 Thomas Waldmann
557 Thomas Waldmann
557 - fixed issue #166 summary pager was skipping 10 revisions on second page
558 - fixed issue #166 summary pager was skipping 10 revisions on second page
558
559
559
560
560 1.1.7 (**2011-03-23**)
561 1.1.7 (**2011-03-23**)
561 ----------------------
562 ----------------------
562
563
563 news
564 news
564 ++++
565 ++++
565
566
566 fixes
567 fixes
567 +++++
568 +++++
568
569
569 - fixed (again) #136 installation support for FreeBSD
570 - fixed (again) #136 installation support for FreeBSD
570
571
571
572
572 1.1.6 (**2011-03-21**)
573 1.1.6 (**2011-03-21**)
573 ----------------------
574 ----------------------
574
575
575 news
576 news
576 ++++
577 ++++
577
578
578 fixes
579 fixes
579 +++++
580 +++++
580
581
581 - fixed #136 installation support for FreeBSD
582 - fixed #136 installation support for FreeBSD
582 - RhodeCode will check for python version during installation
583 - RhodeCode will check for python version during installation
583
584
584 1.1.5 (**2011-03-17**)
585 1.1.5 (**2011-03-17**)
585 ----------------------
586 ----------------------
586
587
587 news
588 news
588 ++++
589 ++++
589
590
590 - basic windows support, by exchanging pybcrypt into sha256 for windows only
591 - basic windows support, by exchanging pybcrypt into sha256 for windows only
591 highly inspired by idea of mantis406
592 highly inspired by idea of mantis406
592
593
593 fixes
594 fixes
594 +++++
595 +++++
595
596
596 - fixed sorting by author in main page
597 - fixed sorting by author in main page
597 - fixed crashes with diffs on binary files
598 - fixed crashes with diffs on binary files
598 - fixed #131 problem with boolean values for LDAP
599 - fixed #131 problem with boolean values for LDAP
599 - fixed #122 mysql problems thanks to striker69
600 - fixed #122 mysql problems thanks to striker69
600 - fixed problem with errors on calling raw/raw_files/annotate functions
601 - fixed problem with errors on calling raw/raw_files/annotate functions
601 with unknown revisions
602 with unknown revisions
602 - fixed returned rawfiles attachment names with international character
603 - fixed returned rawfiles attachment names with international character
603 - cleaned out docs, big thanks to Jason Harris
604 - cleaned out docs, big thanks to Jason Harris
604
605
605 1.1.4 (**2011-02-19**)
606 1.1.4 (**2011-02-19**)
606 ----------------------
607 ----------------------
607
608
608 news
609 news
609 ++++
610 ++++
610
611
611 fixes
612 fixes
612 +++++
613 +++++
613
614
614 - fixed formencode import problem on settings page, that caused server crash
615 - fixed formencode import problem on settings page, that caused server crash
615 when that page was accessed as first after server start
616 when that page was accessed as first after server start
616 - journal fixes
617 - journal fixes
617 - fixed option to access repository just by entering http://server/<repo_name>
618 - fixed option to access repository just by entering http://server/<repo_name>
618
619
619 1.1.3 (**2011-02-16**)
620 1.1.3 (**2011-02-16**)
620 ----------------------
621 ----------------------
621
622
622 news
623 news
623 ++++
624 ++++
624
625
625 - implemented #102 allowing the '.' character in username
626 - implemented #102 allowing the '.' character in username
626 - added option to access repository just by entering http://server/<repo_name>
627 - added option to access repository just by entering http://server/<repo_name>
627 - celery task ignores result for better performance
628 - celery task ignores result for better performance
628
629
629 fixes
630 fixes
630 +++++
631 +++++
631
632
632 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
633 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
633 apollo13 and Johan Walles
634 apollo13 and Johan Walles
634 - small fixes in journal
635 - small fixes in journal
635 - fixed problems with getting setting for celery from .ini files
636 - fixed problems with getting setting for celery from .ini files
636 - registration, password reset and login boxes share the same title as main
637 - registration, password reset and login boxes share the same title as main
637 application now
638 application now
638 - fixed #113: to high permissions to fork repository
639 - fixed #113: to high permissions to fork repository
639 - fixed problem with '[' chars in commit messages in journal
640 - fixed problem with '[' chars in commit messages in journal
640 - removed issue with space inside renamed repository after deletion
641 - removed issue with space inside renamed repository after deletion
641 - db transaction fixes when filesystem repository creation failed
642 - db transaction fixes when filesystem repository creation failed
642 - fixed #106 relation issues on databases different than sqlite
643 - fixed #106 relation issues on databases different than sqlite
643 - fixed static files paths links to use of url() method
644 - fixed static files paths links to use of url() method
644
645
645 1.1.2 (**2011-01-12**)
646 1.1.2 (**2011-01-12**)
646 ----------------------
647 ----------------------
647
648
648 news
649 news
649 ++++
650 ++++
650
651
651
652
652 fixes
653 fixes
653 +++++
654 +++++
654
655
655 - fixes #98 protection against float division of percentage stats
656 - fixes #98 protection against float division of percentage stats
656 - fixed graph bug
657 - fixed graph bug
657 - forced webhelpers version since it was making troubles during installation
658 - forced webhelpers version since it was making troubles during installation
658
659
659 1.1.1 (**2011-01-06**)
660 1.1.1 (**2011-01-06**)
660 ----------------------
661 ----------------------
661
662
662 news
663 news
663 ++++
664 ++++
664
665
665 - added force https option into ini files for easier https usage (no need to
666 - added force https option into ini files for easier https usage (no need to
666 set server headers with this options)
667 set server headers with this options)
667 - small css updates
668 - small css updates
668
669
669 fixes
670 fixes
670 +++++
671 +++++
671
672
672 - fixed #96 redirect loop on files view on repositories without changesets
673 - fixed #96 redirect loop on files view on repositories without changesets
673 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
674 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
674 and server crashed with errors
675 and server crashed with errors
675 - fixed large tooltips problems on main page
676 - fixed large tooltips problems on main page
676 - fixed #92 whoosh indexer is more error proof
677 - fixed #92 whoosh indexer is more error proof
677
678
678 1.1.0 (**2010-12-18**)
679 1.1.0 (**2010-12-18**)
679 ----------------------
680 ----------------------
680
681
681 news
682 news
682 ++++
683 ++++
683
684
684 - rewrite of internals for vcs >=0.1.10
685 - rewrite of internals for vcs >=0.1.10
685 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
686 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
686 with older clients
687 with older clients
687 - anonymous access, authentication via ldap
688 - anonymous access, authentication via ldap
688 - performance upgrade for cached repos list - each repository has its own
689 - performance upgrade for cached repos list - each repository has its own
689 cache that's invalidated when needed.
690 cache that's invalidated when needed.
690 - performance upgrades on repositories with large amount of commits (20K+)
691 - performance upgrades on repositories with large amount of commits (20K+)
691 - main page quick filter for filtering repositories
692 - main page quick filter for filtering repositories
692 - user dashboards with ability to follow chosen repositories actions
693 - user dashboards with ability to follow chosen repositories actions
693 - sends email to admin on new user registration
694 - sends email to admin on new user registration
694 - added cache/statistics reset options into repository settings
695 - added cache/statistics reset options into repository settings
695 - more detailed action logger (based on hooks) with pushed changesets lists
696 - more detailed action logger (based on hooks) with pushed changesets lists
696 and options to disable those hooks from admin panel
697 and options to disable those hooks from admin panel
697 - introduced new enhanced changelog for merges that shows more accurate results
698 - introduced new enhanced changelog for merges that shows more accurate results
698 - new improved and faster code stats (based on pygments lexers mapping tables,
699 - new improved and faster code stats (based on pygments lexers mapping tables,
699 showing up to 10 trending sources for each repository. Additionally stats
700 showing up to 10 trending sources for each repository. Additionally stats
700 can be disabled in repository settings.
701 can be disabled in repository settings.
701 - gui optimizations, fixed application width to 1024px
702 - gui optimizations, fixed application width to 1024px
702 - added cut off (for large files/changesets) limit into config files
703 - added cut off (for large files/changesets) limit into config files
703 - whoosh, celeryd, upgrade moved to paster command
704 - whoosh, celeryd, upgrade moved to paster command
704 - other than sqlite database backends can be used
705 - other than sqlite database backends can be used
705
706
706 fixes
707 fixes
707 +++++
708 +++++
708
709
709 - fixes #61 forked repo was showing only after cache expired
710 - fixes #61 forked repo was showing only after cache expired
710 - fixes #76 no confirmation on user deletes
711 - fixes #76 no confirmation on user deletes
711 - fixes #66 Name field misspelled
712 - fixes #66 Name field misspelled
712 - fixes #72 block user removal when he owns repositories
713 - fixes #72 block user removal when he owns repositories
713 - fixes #69 added password confirmation fields
714 - fixes #69 added password confirmation fields
714 - fixes #87 RhodeCode crashes occasionally on updating repository owner
715 - fixes #87 RhodeCode crashes occasionally on updating repository owner
715 - fixes #82 broken annotations on files with more than 1 blank line at the end
716 - fixes #82 broken annotations on files with more than 1 blank line at the end
716 - a lot of fixes and tweaks for file browser
717 - a lot of fixes and tweaks for file browser
717 - fixed detached session issues
718 - fixed detached session issues
718 - fixed when user had no repos he would see all repos listed in my account
719 - fixed when user had no repos he would see all repos listed in my account
719 - fixed ui() instance bug when global hgrc settings was loaded for server
720 - fixed ui() instance bug when global hgrc settings was loaded for server
720 instance and all hgrc options were merged with our db ui() object
721 instance and all hgrc options were merged with our db ui() object
721 - numerous small bugfixes
722 - numerous small bugfixes
722
723
723 (special thanks for TkSoh for detailed feedback)
724 (special thanks for TkSoh for detailed feedback)
724
725
725
726
726 1.0.2 (**2010-11-12**)
727 1.0.2 (**2010-11-12**)
727 ----------------------
728 ----------------------
728
729
729 news
730 news
730 ++++
731 ++++
731
732
732 - tested under python2.7
733 - tested under python2.7
733 - bumped sqlalchemy and celery versions
734 - bumped sqlalchemy and celery versions
734
735
735 fixes
736 fixes
736 +++++
737 +++++
737
738
738 - fixed #59 missing graph.js
739 - fixed #59 missing graph.js
739 - fixed repo_size crash when repository had broken symlinks
740 - fixed repo_size crash when repository had broken symlinks
740 - fixed python2.5 crashes.
741 - fixed python2.5 crashes.
741
742
742
743
743 1.0.1 (**2010-11-10**)
744 1.0.1 (**2010-11-10**)
744 ----------------------
745 ----------------------
745
746
746 news
747 news
747 ++++
748 ++++
748
749
749 - small css updated
750 - small css updated
750
751
751 fixes
752 fixes
752 +++++
753 +++++
753
754
754 - fixed #53 python2.5 incompatible enumerate calls
755 - fixed #53 python2.5 incompatible enumerate calls
755 - fixed #52 disable mercurial extension for web
756 - fixed #52 disable mercurial extension for web
756 - fixed #51 deleting repositories don't delete it's dependent objects
757 - fixed #51 deleting repositories don't delete it's dependent objects
757
758
758
759
759 1.0.0 (**2010-11-02**)
760 1.0.0 (**2010-11-02**)
760 ----------------------
761 ----------------------
761
762
762 - security bugfix simplehg wasn't checking for permissions on commands
763 - security bugfix simplehg wasn't checking for permissions on commands
763 other than pull or push.
764 other than pull or push.
764 - fixed doubled messages after push or pull in admin journal
765 - fixed doubled messages after push or pull in admin journal
765 - templating and css corrections, fixed repo switcher on chrome, updated titles
766 - templating and css corrections, fixed repo switcher on chrome, updated titles
766 - admin menu accessible from options menu on repository view
767 - admin menu accessible from options menu on repository view
767 - permissions cached queries
768 - permissions cached queries
768
769
769 1.0.0rc4 (**2010-10-12**)
770 1.0.0rc4 (**2010-10-12**)
770 --------------------------
771 --------------------------
771
772
772 - fixed python2.5 missing simplejson imports (thanks to Jens Bäckman)
773 - fixed python2.5 missing simplejson imports (thanks to Jens Bäckman)
773 - removed cache_manager settings from sqlalchemy meta
774 - removed cache_manager settings from sqlalchemy meta
774 - added sqlalchemy cache settings to ini files
775 - added sqlalchemy cache settings to ini files
775 - validated password length and added second try of failure on paster setup-app
776 - validated password length and added second try of failure on paster setup-app
776 - fixed setup database destroy prompt even when there was no db
777 - fixed setup database destroy prompt even when there was no db
777
778
778
779
779 1.0.0rc3 (**2010-10-11**)
780 1.0.0rc3 (**2010-10-11**)
780 -------------------------
781 -------------------------
781
782
782 - fixed i18n during installation.
783 - fixed i18n during installation.
783
784
784 1.0.0rc2 (**2010-10-11**)
785 1.0.0rc2 (**2010-10-11**)
785 -------------------------
786 -------------------------
786
787
787 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
788 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
788 occure. After vcs is fixed it'll be put back again.
789 occure. After vcs is fixed it'll be put back again.
789 - templating/css rewrites, optimized css. No newline at end of file
790 - templating/css rewrites, optimized css.
@@ -1,331 +1,341 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20 #email_prefix = [RhodeCode]
20 #email_prefix = [RhodeCode]
21
21
22 #smtp_server = mail.server.com
22 #smtp_server = mail.server.com
23 #smtp_username =
23 #smtp_username =
24 #smtp_password =
24 #smtp_password =
25 #smtp_port =
25 #smtp_port =
26 #smtp_use_tls = false
26 #smtp_use_tls = false
27 #smtp_use_ssl = true
27 #smtp_use_ssl = true
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 #smtp_auth =
29 #smtp_auth =
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 #threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 #threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 #use_threadpool = true
39 #use_threadpool = true
40
40
41 #use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 use = egg:waitress#main
43 host = 127.0.0.1
43 host = 127.0.0.1
44 port = 8001
44 port = 8001
45
45
46 [filter:proxy-prefix]
46 [filter:proxy-prefix]
47 # prefix middleware for rc
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
49 prefix = /<your-prefix>
50
50
51 [app:main]
51 [app:main]
52 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
53 #filter-with = proxy-prefix
54 full_stack = true
54 full_stack = true
55 static_files = true
55 static_files = true
56 # Optional Languages
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
58 lang = en
58 lang = en
59 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
60 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
61 app_instance_uuid = rc-production
61 app_instance_uuid = rc-production
62 cut_off_limit = 256000
62 cut_off_limit = 256000
63 force_https = false
63 force_https = false
64 commit_parse_limit = 50
64 commit_parse_limit = 50
65 use_gravatar = true
65 use_gravatar = true
66
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
68 ## the following parts of the URL will be replaced
69 ## {email} user email
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
71 ## {size} size of the image that is expected from the server application
72 ## {scheme} http/https from RhodeCode server
72 ## {scheme} http/https from RhodeCode server
73 ## {netloc} network location from RhodeCode server
73 ## {netloc} network location from RhodeCode server
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
76
76
77 container_auth_enabled = false
77 container_auth_enabled = false
78 proxypass_auth_enabled = false
78 proxypass_auth_enabled = false
79 default_encoding = utf8
79 default_encoding = utf8
80
80
81 ## overwrite schema of clone url
81 ## overwrite schema of clone url
82 ## available vars:
82 ## available vars:
83 ## scheme - http/https
83 ## scheme - http/https
84 ## user - current user
84 ## user - current user
85 ## pass - password
85 ## pass - password
86 ## netloc - network location
86 ## netloc - network location
87 ## path - usually repo_name
87 ## path - usually repo_name
88
88
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
90
90
91 ## issue tracking mapping for commits messages
91 ## issue tracking mapping for commits messages
92 ## comment out issue_pat, issue_server, issue_prefix to enable
92 ## comment out issue_pat, issue_server, issue_prefix to enable
93
93
94 ## pattern to get the issues from commit messages
94 ## pattern to get the issues from commit messages
95 ## default one used here is #<numbers> with a regex passive group for `#`
95 ## default one used here is #<numbers> with a regex passive group for `#`
96 ## {id} will be all groups matched from this pattern
96 ## {id} will be all groups matched from this pattern
97
97
98 issue_pat = (?:\s*#)(\d+)
98 issue_pat = (?:\s*#)(\d+)
99
99
100 ## server url to the issue, each {id} will be replaced with match
100 ## server url to the issue, each {id} will be replaced with match
101 ## fetched from the regex and {repo} is replaced with full repository name
101 ## fetched from the regex and {repo} is replaced with full repository name
102 ## including groups {repo_name} is replaced with just name of repo
102 ## including groups {repo_name} is replaced with just name of repo
103
103
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
105
105
106 ## prefix to add to link to indicate it's an url
106 ## prefix to add to link to indicate it's an url
107 ## #314 will be replaced by <issue_prefix><id>
107 ## #314 will be replaced by <issue_prefix><id>
108
108
109 issue_prefix = #
109 issue_prefix = #
110
110
111 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
112 ## multiple patterns, to other issues server, wiki or others
113 ## below an example how to create a wiki pattern
114 # #wiki-some-id -> https://mywiki.com/some-id
115
116 #issue_pat_wiki = (?:wiki-)(.+)
117 #issue_server_link_wiki = https://mywiki.com/{id}
118 #issue_prefix_wiki = WIKI-
119
120
111 ## instance-id prefix
121 ## instance-id prefix
112 ## a prefix key for this instance used for cache invalidation when running
122 ## a prefix key for this instance used for cache invalidation when running
113 ## multiple instances of rhodecode, make sure it's globally unique for
123 ## multiple instances of rhodecode, make sure it's globally unique for
114 ## all running rhodecode instances. Leave empty if you don't use it
124 ## all running rhodecode instances. Leave empty if you don't use it
115 instance_id =
125 instance_id =
116
126
117 ## alternative return HTTP header for failed authentication. Default HTTP
127 ## alternative return HTTP header for failed authentication. Default HTTP
118 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
128 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
119 ## handling that. Set this variable to 403 to return HTTPForbidden
129 ## handling that. Set this variable to 403 to return HTTPForbidden
120 auth_ret_code =
130 auth_ret_code =
121
131
122 ####################################
132 ####################################
123 ### CELERY CONFIG ####
133 ### CELERY CONFIG ####
124 ####################################
134 ####################################
125 use_celery = false
135 use_celery = false
126 broker.host = localhost
136 broker.host = localhost
127 broker.vhost = rabbitmqhost
137 broker.vhost = rabbitmqhost
128 broker.port = 5672
138 broker.port = 5672
129 broker.user = rabbitmq
139 broker.user = rabbitmq
130 broker.password = qweqwe
140 broker.password = qweqwe
131
141
132 celery.imports = rhodecode.lib.celerylib.tasks
142 celery.imports = rhodecode.lib.celerylib.tasks
133
143
134 celery.result.backend = amqp
144 celery.result.backend = amqp
135 celery.result.dburi = amqp://
145 celery.result.dburi = amqp://
136 celery.result.serialier = json
146 celery.result.serialier = json
137
147
138 #celery.send.task.error.emails = true
148 #celery.send.task.error.emails = true
139 #celery.amqp.task.result.expires = 18000
149 #celery.amqp.task.result.expires = 18000
140
150
141 celeryd.concurrency = 2
151 celeryd.concurrency = 2
142 #celeryd.log.file = celeryd.log
152 #celeryd.log.file = celeryd.log
143 celeryd.log.level = debug
153 celeryd.log.level = debug
144 celeryd.max.tasks.per.child = 1
154 celeryd.max.tasks.per.child = 1
145
155
146 #tasks will never be sent to the queue, but executed locally instead.
156 #tasks will never be sent to the queue, but executed locally instead.
147 celery.always.eager = false
157 celery.always.eager = false
148
158
149 ####################################
159 ####################################
150 ### BEAKER CACHE ####
160 ### BEAKER CACHE ####
151 ####################################
161 ####################################
152 beaker.cache.data_dir=%(here)s/data/cache/data
162 beaker.cache.data_dir=%(here)s/data/cache/data
153 beaker.cache.lock_dir=%(here)s/data/cache/lock
163 beaker.cache.lock_dir=%(here)s/data/cache/lock
154
164
155 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
165 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
156
166
157 beaker.cache.super_short_term.type=memory
167 beaker.cache.super_short_term.type=memory
158 beaker.cache.super_short_term.expire=10
168 beaker.cache.super_short_term.expire=10
159 beaker.cache.super_short_term.key_length = 256
169 beaker.cache.super_short_term.key_length = 256
160
170
161 beaker.cache.short_term.type=memory
171 beaker.cache.short_term.type=memory
162 beaker.cache.short_term.expire=60
172 beaker.cache.short_term.expire=60
163 beaker.cache.short_term.key_length = 256
173 beaker.cache.short_term.key_length = 256
164
174
165 beaker.cache.long_term.type=memory
175 beaker.cache.long_term.type=memory
166 beaker.cache.long_term.expire=36000
176 beaker.cache.long_term.expire=36000
167 beaker.cache.long_term.key_length = 256
177 beaker.cache.long_term.key_length = 256
168
178
169 beaker.cache.sql_cache_short.type=memory
179 beaker.cache.sql_cache_short.type=memory
170 beaker.cache.sql_cache_short.expire=10
180 beaker.cache.sql_cache_short.expire=10
171 beaker.cache.sql_cache_short.key_length = 256
181 beaker.cache.sql_cache_short.key_length = 256
172
182
173 beaker.cache.sql_cache_med.type=memory
183 beaker.cache.sql_cache_med.type=memory
174 beaker.cache.sql_cache_med.expire=360
184 beaker.cache.sql_cache_med.expire=360
175 beaker.cache.sql_cache_med.key_length = 256
185 beaker.cache.sql_cache_med.key_length = 256
176
186
177 beaker.cache.sql_cache_long.type=file
187 beaker.cache.sql_cache_long.type=file
178 beaker.cache.sql_cache_long.expire=3600
188 beaker.cache.sql_cache_long.expire=3600
179 beaker.cache.sql_cache_long.key_length = 256
189 beaker.cache.sql_cache_long.key_length = 256
180
190
181 ####################################
191 ####################################
182 ### BEAKER SESSION ####
192 ### BEAKER SESSION ####
183 ####################################
193 ####################################
184 ## Type of storage used for the session, current types are
194 ## Type of storage used for the session, current types are
185 ## dbm, file, memcached, database, and memory.
195 ## dbm, file, memcached, database, and memory.
186 ## The storage uses the Container API
196 ## The storage uses the Container API
187 ## that is also used by the cache system.
197 ## that is also used by the cache system.
188
198
189 ## db session ##
199 ## db session ##
190 #beaker.session.type = ext:database
200 #beaker.session.type = ext:database
191 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
201 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
192 #beaker.session.table_name = db_session
202 #beaker.session.table_name = db_session
193
203
194 ## encrypted cookie client side session, good for many instances ##
204 ## encrypted cookie client side session, good for many instances ##
195 #beaker.session.type = cookie
205 #beaker.session.type = cookie
196
206
197 ## file based cookies (default) ##
207 ## file based cookies (default) ##
198 #beaker.session.type = file
208 #beaker.session.type = file
199
209
200
210
201 beaker.session.key = rhodecode
211 beaker.session.key = rhodecode
202 ## secure cookie requires AES python libraries ##
212 ## secure cookie requires AES python libraries ##
203 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
213 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
204 #beaker.session.validate_key = 9712sds2212c--zxc123
214 #beaker.session.validate_key = 9712sds2212c--zxc123
205 ## sets session as invalid if it haven't been accessed for given amount of time
215 ## sets session as invalid if it haven't been accessed for given amount of time
206 beaker.session.timeout = 2592000
216 beaker.session.timeout = 2592000
207 beaker.session.httponly = true
217 beaker.session.httponly = true
208 #beaker.session.cookie_path = /<your-prefix>
218 #beaker.session.cookie_path = /<your-prefix>
209
219
210 ## uncomment for https secure cookie ##
220 ## uncomment for https secure cookie ##
211 beaker.session.secure = false
221 beaker.session.secure = false
212
222
213 ## auto save the session to not to use .save() ##
223 ## auto save the session to not to use .save() ##
214 beaker.session.auto = False
224 beaker.session.auto = False
215
225
216 ## default cookie expiration time in seconds `true` expire at browser close ##
226 ## default cookie expiration time in seconds `true` expire at browser close ##
217 #beaker.session.cookie_expires = 3600
227 #beaker.session.cookie_expires = 3600
218
228
219
229
220 ################################################################################
230 ################################################################################
221 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
231 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
222 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
232 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
223 ## execute malicious code after an exception is raised. ##
233 ## execute malicious code after an exception is raised. ##
224 ################################################################################
234 ################################################################################
225 set debug = false
235 set debug = false
226
236
227 ##################################
237 ##################################
228 ### LOGVIEW CONFIG ###
238 ### LOGVIEW CONFIG ###
229 ##################################
239 ##################################
230 logview.sqlalchemy = #faa
240 logview.sqlalchemy = #faa
231 logview.pylons.templating = #bfb
241 logview.pylons.templating = #bfb
232 logview.pylons.util = #eee
242 logview.pylons.util = #eee
233
243
234 #########################################################
244 #########################################################
235 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
245 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
236 #########################################################
246 #########################################################
237 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
247 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
238 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
248 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
239 sqlalchemy.db1.echo = false
249 sqlalchemy.db1.echo = false
240 sqlalchemy.db1.pool_recycle = 3600
250 sqlalchemy.db1.pool_recycle = 3600
241 sqlalchemy.db1.convert_unicode = true
251 sqlalchemy.db1.convert_unicode = true
242
252
243 ################################
253 ################################
244 ### LOGGING CONFIGURATION ####
254 ### LOGGING CONFIGURATION ####
245 ################################
255 ################################
246 [loggers]
256 [loggers]
247 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
257 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
248
258
249 [handlers]
259 [handlers]
250 keys = console, console_sql
260 keys = console, console_sql
251
261
252 [formatters]
262 [formatters]
253 keys = generic, color_formatter, color_formatter_sql
263 keys = generic, color_formatter, color_formatter_sql
254
264
255 #############
265 #############
256 ## LOGGERS ##
266 ## LOGGERS ##
257 #############
267 #############
258 [logger_root]
268 [logger_root]
259 level = NOTSET
269 level = NOTSET
260 handlers = console
270 handlers = console
261
271
262 [logger_routes]
272 [logger_routes]
263 level = DEBUG
273 level = DEBUG
264 handlers =
274 handlers =
265 qualname = routes.middleware
275 qualname = routes.middleware
266 # "level = DEBUG" logs the route matched and routing variables.
276 # "level = DEBUG" logs the route matched and routing variables.
267 propagate = 1
277 propagate = 1
268
278
269 [logger_beaker]
279 [logger_beaker]
270 level = DEBUG
280 level = DEBUG
271 handlers =
281 handlers =
272 qualname = beaker.container
282 qualname = beaker.container
273 propagate = 1
283 propagate = 1
274
284
275 [logger_templates]
285 [logger_templates]
276 level = INFO
286 level = INFO
277 handlers =
287 handlers =
278 qualname = pylons.templating
288 qualname = pylons.templating
279 propagate = 1
289 propagate = 1
280
290
281 [logger_rhodecode]
291 [logger_rhodecode]
282 level = DEBUG
292 level = DEBUG
283 handlers =
293 handlers =
284 qualname = rhodecode
294 qualname = rhodecode
285 propagate = 1
295 propagate = 1
286
296
287 [logger_sqlalchemy]
297 [logger_sqlalchemy]
288 level = INFO
298 level = INFO
289 handlers = console_sql
299 handlers = console_sql
290 qualname = sqlalchemy.engine
300 qualname = sqlalchemy.engine
291 propagate = 0
301 propagate = 0
292
302
293 [logger_whoosh_indexer]
303 [logger_whoosh_indexer]
294 level = DEBUG
304 level = DEBUG
295 handlers =
305 handlers =
296 qualname = whoosh_indexer
306 qualname = whoosh_indexer
297 propagate = 1
307 propagate = 1
298
308
299 ##############
309 ##############
300 ## HANDLERS ##
310 ## HANDLERS ##
301 ##############
311 ##############
302
312
303 [handler_console]
313 [handler_console]
304 class = StreamHandler
314 class = StreamHandler
305 args = (sys.stderr,)
315 args = (sys.stderr,)
306 level = INFO
316 level = INFO
307 formatter = generic
317 formatter = generic
308
318
309 [handler_console_sql]
319 [handler_console_sql]
310 class = StreamHandler
320 class = StreamHandler
311 args = (sys.stderr,)
321 args = (sys.stderr,)
312 level = WARN
322 level = WARN
313 formatter = generic
323 formatter = generic
314
324
315 ################
325 ################
316 ## FORMATTERS ##
326 ## FORMATTERS ##
317 ################
327 ################
318
328
319 [formatter_generic]
329 [formatter_generic]
320 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
330 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
321 datefmt = %Y-%m-%d %H:%M:%S
331 datefmt = %Y-%m-%d %H:%M:%S
322
332
323 [formatter_color_formatter]
333 [formatter_color_formatter]
324 class=rhodecode.lib.colored_formatter.ColorFormatter
334 class=rhodecode.lib.colored_formatter.ColorFormatter
325 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
335 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
326 datefmt = %Y-%m-%d %H:%M:%S
336 datefmt = %Y-%m-%d %H:%M:%S
327
337
328 [formatter_color_formatter_sql]
338 [formatter_color_formatter_sql]
329 class=rhodecode.lib.colored_formatter.ColorFormatterSql
339 class=rhodecode.lib.colored_formatter.ColorFormatterSql
330 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
340 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
331 datefmt = %Y-%m-%d %H:%M:%S
341 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,341 +1,351 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20 #email_prefix = [RhodeCode]
20 #email_prefix = [RhodeCode]
21
21
22 #smtp_server = mail.server.com
22 #smtp_server = mail.server.com
23 #smtp_username =
23 #smtp_username =
24 #smtp_password =
24 #smtp_password =
25 #smtp_port =
25 #smtp_port =
26 #smtp_use_tls = false
26 #smtp_use_tls = false
27 #smtp_use_ssl = true
27 #smtp_use_ssl = true
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 #smtp_auth =
29 #smtp_auth =
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 #threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 #threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 #use_threadpool = true
39 #use_threadpool = true
40
40
41 #use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 use = egg:waitress#main
43 host = 127.0.0.1
43 host = 127.0.0.1
44 port = 5000
44 port = 5000
45
45
46 [filter:proxy-prefix]
46 [filter:proxy-prefix]
47 # prefix middleware for rc
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
49 prefix = /<your-prefix>
50
50
51 [app:main]
51 [app:main]
52 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
53 #filter-with = proxy-prefix
54 full_stack = true
54 full_stack = true
55 static_files = true
55 static_files = true
56 # Optional Languages
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
58 lang = en
58 lang = en
59 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
60 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
61 app_instance_uuid = ${app_instance_uuid}
61 app_instance_uuid = ${app_instance_uuid}
62 cut_off_limit = 256000
62 cut_off_limit = 256000
63 force_https = false
63 force_https = false
64 commit_parse_limit = 50
64 commit_parse_limit = 50
65 use_gravatar = true
65 use_gravatar = true
66
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
68 ## the following parts of the URL will be replaced
69 ## {email} user email
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
71 ## {size} size of the image that is expected from the server application
72 ## {scheme} http/https from RhodeCode server
72 ## {scheme} http/https from RhodeCode server
73 ## {netloc} network location from RhodeCode server
73 ## {netloc} network location from RhodeCode server
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
74 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
75 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
76
76
77 container_auth_enabled = false
77 container_auth_enabled = false
78 proxypass_auth_enabled = false
78 proxypass_auth_enabled = false
79 default_encoding = utf8
79 default_encoding = utf8
80
80
81 ## overwrite schema of clone url
81 ## overwrite schema of clone url
82 ## available vars:
82 ## available vars:
83 ## scheme - http/https
83 ## scheme - http/https
84 ## user - current user
84 ## user - current user
85 ## pass - password
85 ## pass - password
86 ## netloc - network location
86 ## netloc - network location
87 ## path - usually repo_name
87 ## path - usually repo_name
88
88
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
89 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
90
90
91 ## issue tracking mapping for commits messages
91 ## issue tracking mapping for commits messages
92 ## comment out issue_pat, issue_server, issue_prefix to enable
92 ## comment out issue_pat, issue_server, issue_prefix to enable
93
93
94 ## pattern to get the issues from commit messages
94 ## pattern to get the issues from commit messages
95 ## default one used here is #<numbers> with a regex passive group for `#`
95 ## default one used here is #<numbers> with a regex passive group for `#`
96 ## {id} will be all groups matched from this pattern
96 ## {id} will be all groups matched from this pattern
97
97
98 issue_pat = (?:\s*#)(\d+)
98 issue_pat = (?:\s*#)(\d+)
99
99
100 ## server url to the issue, each {id} will be replaced with match
100 ## server url to the issue, each {id} will be replaced with match
101 ## fetched from the regex and {repo} is replaced with full repository name
101 ## fetched from the regex and {repo} is replaced with full repository name
102 ## including groups {repo_name} is replaced with just name of repo
102 ## including groups {repo_name} is replaced with just name of repo
103
103
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
104 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
105
105
106 ## prefix to add to link to indicate it's an url
106 ## prefix to add to link to indicate it's an url
107 ## #314 will be replaced by <issue_prefix><id>
107 ## #314 will be replaced by <issue_prefix><id>
108
108
109 issue_prefix = #
109 issue_prefix = #
110
110
111 ## issue_pat, issue_server_link, issue_prefix can have suffixes to specify
112 ## multiple patterns, to other issues server, wiki or others
113 ## below an example how to create a wiki pattern
114 # #wiki-some-id -> https://mywiki.com/some-id
115
116 #issue_pat_wiki = (?:wiki-)(.+)
117 #issue_server_link_wiki = https://mywiki.com/{id}
118 #issue_prefix_wiki = WIKI-
119
120
111 ## instance-id prefix
121 ## instance-id prefix
112 ## a prefix key for this instance used for cache invalidation when running
122 ## a prefix key for this instance used for cache invalidation when running
113 ## multiple instances of rhodecode, make sure it's globally unique for
123 ## multiple instances of rhodecode, make sure it's globally unique for
114 ## all running rhodecode instances. Leave empty if you don't use it
124 ## all running rhodecode instances. Leave empty if you don't use it
115 instance_id =
125 instance_id =
116
126
117 ## alternative return HTTP header for failed authentication. Default HTTP
127 ## alternative return HTTP header for failed authentication. Default HTTP
118 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
128 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
119 ## handling that. Set this variable to 403 to return HTTPForbidden
129 ## handling that. Set this variable to 403 to return HTTPForbidden
120 auth_ret_code =
130 auth_ret_code =
121
131
122 ####################################
132 ####################################
123 ### CELERY CONFIG ####
133 ### CELERY CONFIG ####
124 ####################################
134 ####################################
125 use_celery = false
135 use_celery = false
126 broker.host = localhost
136 broker.host = localhost
127 broker.vhost = rabbitmqhost
137 broker.vhost = rabbitmqhost
128 broker.port = 5672
138 broker.port = 5672
129 broker.user = rabbitmq
139 broker.user = rabbitmq
130 broker.password = qweqwe
140 broker.password = qweqwe
131
141
132 celery.imports = rhodecode.lib.celerylib.tasks
142 celery.imports = rhodecode.lib.celerylib.tasks
133
143
134 celery.result.backend = amqp
144 celery.result.backend = amqp
135 celery.result.dburi = amqp://
145 celery.result.dburi = amqp://
136 celery.result.serialier = json
146 celery.result.serialier = json
137
147
138 #celery.send.task.error.emails = true
148 #celery.send.task.error.emails = true
139 #celery.amqp.task.result.expires = 18000
149 #celery.amqp.task.result.expires = 18000
140
150
141 celeryd.concurrency = 2
151 celeryd.concurrency = 2
142 #celeryd.log.file = celeryd.log
152 #celeryd.log.file = celeryd.log
143 celeryd.log.level = debug
153 celeryd.log.level = debug
144 celeryd.max.tasks.per.child = 1
154 celeryd.max.tasks.per.child = 1
145
155
146 #tasks will never be sent to the queue, but executed locally instead.
156 #tasks will never be sent to the queue, but executed locally instead.
147 celery.always.eager = false
157 celery.always.eager = false
148
158
149 ####################################
159 ####################################
150 ### BEAKER CACHE ####
160 ### BEAKER CACHE ####
151 ####################################
161 ####################################
152 beaker.cache.data_dir=%(here)s/data/cache/data
162 beaker.cache.data_dir=%(here)s/data/cache/data
153 beaker.cache.lock_dir=%(here)s/data/cache/lock
163 beaker.cache.lock_dir=%(here)s/data/cache/lock
154
164
155 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
165 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
156
166
157 beaker.cache.super_short_term.type=memory
167 beaker.cache.super_short_term.type=memory
158 beaker.cache.super_short_term.expire=10
168 beaker.cache.super_short_term.expire=10
159 beaker.cache.super_short_term.key_length = 256
169 beaker.cache.super_short_term.key_length = 256
160
170
161 beaker.cache.short_term.type=memory
171 beaker.cache.short_term.type=memory
162 beaker.cache.short_term.expire=60
172 beaker.cache.short_term.expire=60
163 beaker.cache.short_term.key_length = 256
173 beaker.cache.short_term.key_length = 256
164
174
165 beaker.cache.long_term.type=memory
175 beaker.cache.long_term.type=memory
166 beaker.cache.long_term.expire=36000
176 beaker.cache.long_term.expire=36000
167 beaker.cache.long_term.key_length = 256
177 beaker.cache.long_term.key_length = 256
168
178
169 beaker.cache.sql_cache_short.type=memory
179 beaker.cache.sql_cache_short.type=memory
170 beaker.cache.sql_cache_short.expire=10
180 beaker.cache.sql_cache_short.expire=10
171 beaker.cache.sql_cache_short.key_length = 256
181 beaker.cache.sql_cache_short.key_length = 256
172
182
173 beaker.cache.sql_cache_med.type=memory
183 beaker.cache.sql_cache_med.type=memory
174 beaker.cache.sql_cache_med.expire=360
184 beaker.cache.sql_cache_med.expire=360
175 beaker.cache.sql_cache_med.key_length = 256
185 beaker.cache.sql_cache_med.key_length = 256
176
186
177 beaker.cache.sql_cache_long.type=file
187 beaker.cache.sql_cache_long.type=file
178 beaker.cache.sql_cache_long.expire=3600
188 beaker.cache.sql_cache_long.expire=3600
179 beaker.cache.sql_cache_long.key_length = 256
189 beaker.cache.sql_cache_long.key_length = 256
180
190
181 ####################################
191 ####################################
182 ### BEAKER SESSION ####
192 ### BEAKER SESSION ####
183 ####################################
193 ####################################
184 ## Type of storage used for the session, current types are
194 ## Type of storage used for the session, current types are
185 ## dbm, file, memcached, database, and memory.
195 ## dbm, file, memcached, database, and memory.
186 ## The storage uses the Container API
196 ## The storage uses the Container API
187 ## that is also used by the cache system.
197 ## that is also used by the cache system.
188
198
189 ## db session ##
199 ## db session ##
190 #beaker.session.type = ext:database
200 #beaker.session.type = ext:database
191 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
201 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
192 #beaker.session.table_name = db_session
202 #beaker.session.table_name = db_session
193
203
194 ## encrypted cookie client side session, good for many instances ##
204 ## encrypted cookie client side session, good for many instances ##
195 #beaker.session.type = cookie
205 #beaker.session.type = cookie
196
206
197 ## file based cookies (default) ##
207 ## file based cookies (default) ##
198 #beaker.session.type = file
208 #beaker.session.type = file
199
209
200
210
201 beaker.session.key = rhodecode
211 beaker.session.key = rhodecode
202 ## secure cookie requires AES python libraries ##
212 ## secure cookie requires AES python libraries ##
203 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
213 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
204 #beaker.session.validate_key = 9712sds2212c--zxc123
214 #beaker.session.validate_key = 9712sds2212c--zxc123
205 ## sets session as invalid if it haven't been accessed for given amount of time
215 ## sets session as invalid if it haven't been accessed for given amount of time
206 beaker.session.timeout = 2592000
216 beaker.session.timeout = 2592000
207 beaker.session.httponly = true
217 beaker.session.httponly = true
208 #beaker.session.cookie_path = /<your-prefix>
218 #beaker.session.cookie_path = /<your-prefix>
209
219
210 ## uncomment for https secure cookie ##
220 ## uncomment for https secure cookie ##
211 beaker.session.secure = false
221 beaker.session.secure = false
212
222
213 ## auto save the session to not to use .save() ##
223 ## auto save the session to not to use .save() ##
214 beaker.session.auto = False
224 beaker.session.auto = False
215
225
216 ## default cookie expiration time in seconds `true` expire at browser close ##
226 ## default cookie expiration time in seconds `true` expire at browser close ##
217 #beaker.session.cookie_expires = 3600
227 #beaker.session.cookie_expires = 3600
218
228
219
229
220 ################################################################################
230 ################################################################################
221 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
231 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
222 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
232 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
223 ## execute malicious code after an exception is raised. ##
233 ## execute malicious code after an exception is raised. ##
224 ################################################################################
234 ################################################################################
225 set debug = false
235 set debug = false
226
236
227 ##################################
237 ##################################
228 ### LOGVIEW CONFIG ###
238 ### LOGVIEW CONFIG ###
229 ##################################
239 ##################################
230 logview.sqlalchemy = #faa
240 logview.sqlalchemy = #faa
231 logview.pylons.templating = #bfb
241 logview.pylons.templating = #bfb
232 logview.pylons.util = #eee
242 logview.pylons.util = #eee
233
243
234 #########################################################
244 #########################################################
235 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
245 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
236 #########################################################
246 #########################################################
237
247
238 # SQLITE [default]
248 # SQLITE [default]
239 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
249 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
240
250
241 # POSTGRESQL
251 # POSTGRESQL
242 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
252 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
243
253
244 # MySQL
254 # MySQL
245 # sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
255 # sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
246
256
247 # see sqlalchemy docs for others
257 # see sqlalchemy docs for others
248
258
249 sqlalchemy.db1.echo = false
259 sqlalchemy.db1.echo = false
250 sqlalchemy.db1.pool_recycle = 3600
260 sqlalchemy.db1.pool_recycle = 3600
251 sqlalchemy.db1.convert_unicode = true
261 sqlalchemy.db1.convert_unicode = true
252
262
253 ################################
263 ################################
254 ### LOGGING CONFIGURATION ####
264 ### LOGGING CONFIGURATION ####
255 ################################
265 ################################
256 [loggers]
266 [loggers]
257 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
267 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, whoosh_indexer
258
268
259 [handlers]
269 [handlers]
260 keys = console, console_sql
270 keys = console, console_sql
261
271
262 [formatters]
272 [formatters]
263 keys = generic, color_formatter, color_formatter_sql
273 keys = generic, color_formatter, color_formatter_sql
264
274
265 #############
275 #############
266 ## LOGGERS ##
276 ## LOGGERS ##
267 #############
277 #############
268 [logger_root]
278 [logger_root]
269 level = NOTSET
279 level = NOTSET
270 handlers = console
280 handlers = console
271
281
272 [logger_routes]
282 [logger_routes]
273 level = DEBUG
283 level = DEBUG
274 handlers =
284 handlers =
275 qualname = routes.middleware
285 qualname = routes.middleware
276 # "level = DEBUG" logs the route matched and routing variables.
286 # "level = DEBUG" logs the route matched and routing variables.
277 propagate = 1
287 propagate = 1
278
288
279 [logger_beaker]
289 [logger_beaker]
280 level = DEBUG
290 level = DEBUG
281 handlers =
291 handlers =
282 qualname = beaker.container
292 qualname = beaker.container
283 propagate = 1
293 propagate = 1
284
294
285 [logger_templates]
295 [logger_templates]
286 level = INFO
296 level = INFO
287 handlers =
297 handlers =
288 qualname = pylons.templating
298 qualname = pylons.templating
289 propagate = 1
299 propagate = 1
290
300
291 [logger_rhodecode]
301 [logger_rhodecode]
292 level = DEBUG
302 level = DEBUG
293 handlers =
303 handlers =
294 qualname = rhodecode
304 qualname = rhodecode
295 propagate = 1
305 propagate = 1
296
306
297 [logger_sqlalchemy]
307 [logger_sqlalchemy]
298 level = INFO
308 level = INFO
299 handlers = console_sql
309 handlers = console_sql
300 qualname = sqlalchemy.engine
310 qualname = sqlalchemy.engine
301 propagate = 0
311 propagate = 0
302
312
303 [logger_whoosh_indexer]
313 [logger_whoosh_indexer]
304 level = DEBUG
314 level = DEBUG
305 handlers =
315 handlers =
306 qualname = whoosh_indexer
316 qualname = whoosh_indexer
307 propagate = 1
317 propagate = 1
308
318
309 ##############
319 ##############
310 ## HANDLERS ##
320 ## HANDLERS ##
311 ##############
321 ##############
312
322
313 [handler_console]
323 [handler_console]
314 class = StreamHandler
324 class = StreamHandler
315 args = (sys.stderr,)
325 args = (sys.stderr,)
316 level = INFO
326 level = INFO
317 formatter = generic
327 formatter = generic
318
328
319 [handler_console_sql]
329 [handler_console_sql]
320 class = StreamHandler
330 class = StreamHandler
321 args = (sys.stderr,)
331 args = (sys.stderr,)
322 level = WARN
332 level = WARN
323 formatter = generic
333 formatter = generic
324
334
325 ################
335 ################
326 ## FORMATTERS ##
336 ## FORMATTERS ##
327 ################
337 ################
328
338
329 [formatter_generic]
339 [formatter_generic]
330 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
340 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
331 datefmt = %Y-%m-%d %H:%M:%S
341 datefmt = %Y-%m-%d %H:%M:%S
332
342
333 [formatter_color_formatter]
343 [formatter_color_formatter]
334 class=rhodecode.lib.colored_formatter.ColorFormatter
344 class=rhodecode.lib.colored_formatter.ColorFormatter
335 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
345 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
336 datefmt = %Y-%m-%d %H:%M:%S
346 datefmt = %Y-%m-%d %H:%M:%S
337
347
338 [formatter_color_formatter_sql]
348 [formatter_color_formatter_sql]
339 class=rhodecode.lib.colored_formatter.ColorFormatterSql
349 class=rhodecode.lib.colored_formatter.ColorFormatterSql
340 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
350 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
341 datefmt = %Y-%m-%d %H:%M:%S
351 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,1093 +1,1096 b''
1 """Helper functions
1 """Helper functions
2
2
3 Consists of functions to typically be used within templates, but also
3 Consists of functions to typically be used within templates, but also
4 available to Controllers. This module is available to both as 'h'.
4 available to Controllers. This module is available to both as 'h'.
5 """
5 """
6 import random
6 import random
7 import hashlib
7 import hashlib
8 import StringIO
8 import StringIO
9 import urllib
9 import urllib
10 import math
10 import math
11 import logging
11 import logging
12 import re
12 import re
13 import urlparse
13 import urlparse
14
14
15 from datetime import datetime
15 from datetime import datetime
16 from pygments.formatters.html import HtmlFormatter
16 from pygments.formatters.html import HtmlFormatter
17 from pygments import highlight as code_highlight
17 from pygments import highlight as code_highlight
18 from pylons import url, request, config
18 from pylons import url, request, config
19 from pylons.i18n.translation import _, ungettext
19 from pylons.i18n.translation import _, ungettext
20 from hashlib import md5
20 from hashlib import md5
21
21
22 from webhelpers.html import literal, HTML, escape
22 from webhelpers.html import literal, HTML, escape
23 from webhelpers.html.tools import *
23 from webhelpers.html.tools import *
24 from webhelpers.html.builder import make_tag
24 from webhelpers.html.builder import make_tag
25 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
25 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
26 end_form, file, form, hidden, image, javascript_link, link_to, \
26 end_form, file, form, hidden, image, javascript_link, link_to, \
27 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
27 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
28 submit, text, password, textarea, title, ul, xml_declaration, radio
28 submit, text, password, textarea, title, ul, xml_declaration, radio
29 from webhelpers.html.tools import auto_link, button_to, highlight, \
29 from webhelpers.html.tools import auto_link, button_to, highlight, \
30 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
30 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
31 from webhelpers.number import format_byte_size, format_bit_size
31 from webhelpers.number import format_byte_size, format_bit_size
32 from webhelpers.pylonslib import Flash as _Flash
32 from webhelpers.pylonslib import Flash as _Flash
33 from webhelpers.pylonslib.secure_form import secure_form
33 from webhelpers.pylonslib.secure_form import secure_form
34 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
34 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
35 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
35 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
36 replace_whitespace, urlify, truncate, wrap_paragraphs
36 replace_whitespace, urlify, truncate, wrap_paragraphs
37 from webhelpers.date import time_ago_in_words
37 from webhelpers.date import time_ago_in_words
38 from webhelpers.paginate import Page
38 from webhelpers.paginate import Page
39 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
39 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
40 convert_boolean_attrs, NotGiven, _make_safe_id_component
40 convert_boolean_attrs, NotGiven, _make_safe_id_component
41
41
42 from rhodecode.lib.annotate import annotate_highlight
42 from rhodecode.lib.annotate import annotate_highlight
43 from rhodecode.lib.utils import repo_name_slug
43 from rhodecode.lib.utils import repo_name_slug
44 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
44 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
45 get_changeset_safe, datetime_to_time, time_to_datetime
45 get_changeset_safe, datetime_to_time, time_to_datetime
46 from rhodecode.lib.markup_renderer import MarkupRenderer
46 from rhodecode.lib.markup_renderer import MarkupRenderer
47 from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError
47 from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError
48 from rhodecode.lib.vcs.backends.base import BaseChangeset
48 from rhodecode.lib.vcs.backends.base import BaseChangeset
49 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
49 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
50 from rhodecode.model.changeset_status import ChangesetStatusModel
50 from rhodecode.model.changeset_status import ChangesetStatusModel
51 from rhodecode.model.db import URL_SEP, Permission
51 from rhodecode.model.db import URL_SEP, Permission
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 html_escape_table = {
56 html_escape_table = {
57 "&": "&amp;",
57 "&": "&amp;",
58 '"': "&quot;",
58 '"': "&quot;",
59 "'": "&apos;",
59 "'": "&apos;",
60 ">": "&gt;",
60 ">": "&gt;",
61 "<": "&lt;",
61 "<": "&lt;",
62 }
62 }
63
63
64
64
65 def html_escape(text):
65 def html_escape(text):
66 """Produce entities within text."""
66 """Produce entities within text."""
67 return "".join(html_escape_table.get(c,c) for c in text)
67 return "".join(html_escape_table.get(c,c) for c in text)
68
68
69
69
70 def shorter(text, size=20):
70 def shorter(text, size=20):
71 postfix = '...'
71 postfix = '...'
72 if len(text) > size:
72 if len(text) > size:
73 return text[:size - len(postfix)] + postfix
73 return text[:size - len(postfix)] + postfix
74 return text
74 return text
75
75
76
76
77 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
77 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
78 """
78 """
79 Reset button
79 Reset button
80 """
80 """
81 _set_input_attrs(attrs, type, name, value)
81 _set_input_attrs(attrs, type, name, value)
82 _set_id_attr(attrs, id, name)
82 _set_id_attr(attrs, id, name)
83 convert_boolean_attrs(attrs, ["disabled"])
83 convert_boolean_attrs(attrs, ["disabled"])
84 return HTML.input(**attrs)
84 return HTML.input(**attrs)
85
85
86 reset = _reset
86 reset = _reset
87 safeid = _make_safe_id_component
87 safeid = _make_safe_id_component
88
88
89
89
90 def FID(raw_id, path):
90 def FID(raw_id, path):
91 """
91 """
92 Creates a uniqe ID for filenode based on it's hash of path and revision
92 Creates a uniqe ID for filenode based on it's hash of path and revision
93 it's safe to use in urls
93 it's safe to use in urls
94
94
95 :param raw_id:
95 :param raw_id:
96 :param path:
96 :param path:
97 """
97 """
98
98
99 return 'C-%s-%s' % (short_id(raw_id), md5(safe_str(path)).hexdigest()[:12])
99 return 'C-%s-%s' % (short_id(raw_id), md5(safe_str(path)).hexdigest()[:12])
100
100
101
101
102 def get_token():
102 def get_token():
103 """Return the current authentication token, creating one if one doesn't
103 """Return the current authentication token, creating one if one doesn't
104 already exist.
104 already exist.
105 """
105 """
106 token_key = "_authentication_token"
106 token_key = "_authentication_token"
107 from pylons import session
107 from pylons import session
108 if not token_key in session:
108 if not token_key in session:
109 try:
109 try:
110 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
110 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
111 except AttributeError: # Python < 2.4
111 except AttributeError: # Python < 2.4
112 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
112 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
113 session[token_key] = token
113 session[token_key] = token
114 if hasattr(session, 'save'):
114 if hasattr(session, 'save'):
115 session.save()
115 session.save()
116 return session[token_key]
116 return session[token_key]
117
117
118
118
119 class _GetError(object):
119 class _GetError(object):
120 """Get error from form_errors, and represent it as span wrapped error
120 """Get error from form_errors, and represent it as span wrapped error
121 message
121 message
122
122
123 :param field_name: field to fetch errors for
123 :param field_name: field to fetch errors for
124 :param form_errors: form errors dict
124 :param form_errors: form errors dict
125 """
125 """
126
126
127 def __call__(self, field_name, form_errors):
127 def __call__(self, field_name, form_errors):
128 tmpl = """<span class="error_msg">%s</span>"""
128 tmpl = """<span class="error_msg">%s</span>"""
129 if form_errors and field_name in form_errors:
129 if form_errors and field_name in form_errors:
130 return literal(tmpl % form_errors.get(field_name))
130 return literal(tmpl % form_errors.get(field_name))
131
131
132 get_error = _GetError()
132 get_error = _GetError()
133
133
134
134
135 class _ToolTip(object):
135 class _ToolTip(object):
136
136
137 def __call__(self, tooltip_title, trim_at=50):
137 def __call__(self, tooltip_title, trim_at=50):
138 """
138 """
139 Special function just to wrap our text into nice formatted
139 Special function just to wrap our text into nice formatted
140 autowrapped text
140 autowrapped text
141
141
142 :param tooltip_title:
142 :param tooltip_title:
143 """
143 """
144 tooltip_title = escape(tooltip_title)
144 tooltip_title = escape(tooltip_title)
145 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
145 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
146 return tooltip_title
146 return tooltip_title
147 tooltip = _ToolTip()
147 tooltip = _ToolTip()
148
148
149
149
150 class _FilesBreadCrumbs(object):
150 class _FilesBreadCrumbs(object):
151
151
152 def __call__(self, repo_name, rev, paths):
152 def __call__(self, repo_name, rev, paths):
153 if isinstance(paths, str):
153 if isinstance(paths, str):
154 paths = safe_unicode(paths)
154 paths = safe_unicode(paths)
155 url_l = [link_to(repo_name, url('files_home',
155 url_l = [link_to(repo_name, url('files_home',
156 repo_name=repo_name,
156 repo_name=repo_name,
157 revision=rev, f_path=''),
157 revision=rev, f_path=''),
158 class_='ypjax-link')]
158 class_='ypjax-link')]
159 paths_l = paths.split('/')
159 paths_l = paths.split('/')
160 for cnt, p in enumerate(paths_l):
160 for cnt, p in enumerate(paths_l):
161 if p != '':
161 if p != '':
162 url_l.append(link_to(p,
162 url_l.append(link_to(p,
163 url('files_home',
163 url('files_home',
164 repo_name=repo_name,
164 repo_name=repo_name,
165 revision=rev,
165 revision=rev,
166 f_path='/'.join(paths_l[:cnt + 1])
166 f_path='/'.join(paths_l[:cnt + 1])
167 ),
167 ),
168 class_='ypjax-link'
168 class_='ypjax-link'
169 )
169 )
170 )
170 )
171
171
172 return literal('/'.join(url_l))
172 return literal('/'.join(url_l))
173
173
174 files_breadcrumbs = _FilesBreadCrumbs()
174 files_breadcrumbs = _FilesBreadCrumbs()
175
175
176
176
177 class CodeHtmlFormatter(HtmlFormatter):
177 class CodeHtmlFormatter(HtmlFormatter):
178 """
178 """
179 My code Html Formatter for source codes
179 My code Html Formatter for source codes
180 """
180 """
181
181
182 def wrap(self, source, outfile):
182 def wrap(self, source, outfile):
183 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
183 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
184
184
185 def _wrap_code(self, source):
185 def _wrap_code(self, source):
186 for cnt, it in enumerate(source):
186 for cnt, it in enumerate(source):
187 i, t = it
187 i, t = it
188 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
188 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
189 yield i, t
189 yield i, t
190
190
191 def _wrap_tablelinenos(self, inner):
191 def _wrap_tablelinenos(self, inner):
192 dummyoutfile = StringIO.StringIO()
192 dummyoutfile = StringIO.StringIO()
193 lncount = 0
193 lncount = 0
194 for t, line in inner:
194 for t, line in inner:
195 if t:
195 if t:
196 lncount += 1
196 lncount += 1
197 dummyoutfile.write(line)
197 dummyoutfile.write(line)
198
198
199 fl = self.linenostart
199 fl = self.linenostart
200 mw = len(str(lncount + fl - 1))
200 mw = len(str(lncount + fl - 1))
201 sp = self.linenospecial
201 sp = self.linenospecial
202 st = self.linenostep
202 st = self.linenostep
203 la = self.lineanchors
203 la = self.lineanchors
204 aln = self.anchorlinenos
204 aln = self.anchorlinenos
205 nocls = self.noclasses
205 nocls = self.noclasses
206 if sp:
206 if sp:
207 lines = []
207 lines = []
208
208
209 for i in range(fl, fl + lncount):
209 for i in range(fl, fl + lncount):
210 if i % st == 0:
210 if i % st == 0:
211 if i % sp == 0:
211 if i % sp == 0:
212 if aln:
212 if aln:
213 lines.append('<a href="#%s%d" class="special">%*d</a>' %
213 lines.append('<a href="#%s%d" class="special">%*d</a>' %
214 (la, i, mw, i))
214 (la, i, mw, i))
215 else:
215 else:
216 lines.append('<span class="special">%*d</span>' % (mw, i))
216 lines.append('<span class="special">%*d</span>' % (mw, i))
217 else:
217 else:
218 if aln:
218 if aln:
219 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
219 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
220 else:
220 else:
221 lines.append('%*d' % (mw, i))
221 lines.append('%*d' % (mw, i))
222 else:
222 else:
223 lines.append('')
223 lines.append('')
224 ls = '\n'.join(lines)
224 ls = '\n'.join(lines)
225 else:
225 else:
226 lines = []
226 lines = []
227 for i in range(fl, fl + lncount):
227 for i in range(fl, fl + lncount):
228 if i % st == 0:
228 if i % st == 0:
229 if aln:
229 if aln:
230 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
230 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
231 else:
231 else:
232 lines.append('%*d' % (mw, i))
232 lines.append('%*d' % (mw, i))
233 else:
233 else:
234 lines.append('')
234 lines.append('')
235 ls = '\n'.join(lines)
235 ls = '\n'.join(lines)
236
236
237 # in case you wonder about the seemingly redundant <div> here: since the
237 # in case you wonder about the seemingly redundant <div> here: since the
238 # content in the other cell also is wrapped in a div, some browsers in
238 # content in the other cell also is wrapped in a div, some browsers in
239 # some configurations seem to mess up the formatting...
239 # some configurations seem to mess up the formatting...
240 if nocls:
240 if nocls:
241 yield 0, ('<table class="%stable">' % self.cssclass +
241 yield 0, ('<table class="%stable">' % self.cssclass +
242 '<tr><td><div class="linenodiv" '
242 '<tr><td><div class="linenodiv" '
243 'style="background-color: #f0f0f0; padding-right: 10px">'
243 'style="background-color: #f0f0f0; padding-right: 10px">'
244 '<pre style="line-height: 125%">' +
244 '<pre style="line-height: 125%">' +
245 ls + '</pre></div></td><td id="hlcode" class="code">')
245 ls + '</pre></div></td><td id="hlcode" class="code">')
246 else:
246 else:
247 yield 0, ('<table class="%stable">' % self.cssclass +
247 yield 0, ('<table class="%stable">' % self.cssclass +
248 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
248 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
249 ls + '</pre></div></td><td id="hlcode" class="code">')
249 ls + '</pre></div></td><td id="hlcode" class="code">')
250 yield 0, dummyoutfile.getvalue()
250 yield 0, dummyoutfile.getvalue()
251 yield 0, '</td></tr></table>'
251 yield 0, '</td></tr></table>'
252
252
253
253
254 def pygmentize(filenode, **kwargs):
254 def pygmentize(filenode, **kwargs):
255 """pygmentize function using pygments
255 """pygmentize function using pygments
256
256
257 :param filenode:
257 :param filenode:
258 """
258 """
259
259
260 return literal(code_highlight(filenode.content,
260 return literal(code_highlight(filenode.content,
261 filenode.lexer, CodeHtmlFormatter(**kwargs)))
261 filenode.lexer, CodeHtmlFormatter(**kwargs)))
262
262
263
263
264 def pygmentize_annotation(repo_name, filenode, **kwargs):
264 def pygmentize_annotation(repo_name, filenode, **kwargs):
265 """
265 """
266 pygmentize function for annotation
266 pygmentize function for annotation
267
267
268 :param filenode:
268 :param filenode:
269 """
269 """
270
270
271 color_dict = {}
271 color_dict = {}
272
272
273 def gen_color(n=10000):
273 def gen_color(n=10000):
274 """generator for getting n of evenly distributed colors using
274 """generator for getting n of evenly distributed colors using
275 hsv color and golden ratio. It always return same order of colors
275 hsv color and golden ratio. It always return same order of colors
276
276
277 :returns: RGB tuple
277 :returns: RGB tuple
278 """
278 """
279
279
280 def hsv_to_rgb(h, s, v):
280 def hsv_to_rgb(h, s, v):
281 if s == 0.0:
281 if s == 0.0:
282 return v, v, v
282 return v, v, v
283 i = int(h * 6.0) # XXX assume int() truncates!
283 i = int(h * 6.0) # XXX assume int() truncates!
284 f = (h * 6.0) - i
284 f = (h * 6.0) - i
285 p = v * (1.0 - s)
285 p = v * (1.0 - s)
286 q = v * (1.0 - s * f)
286 q = v * (1.0 - s * f)
287 t = v * (1.0 - s * (1.0 - f))
287 t = v * (1.0 - s * (1.0 - f))
288 i = i % 6
288 i = i % 6
289 if i == 0:
289 if i == 0:
290 return v, t, p
290 return v, t, p
291 if i == 1:
291 if i == 1:
292 return q, v, p
292 return q, v, p
293 if i == 2:
293 if i == 2:
294 return p, v, t
294 return p, v, t
295 if i == 3:
295 if i == 3:
296 return p, q, v
296 return p, q, v
297 if i == 4:
297 if i == 4:
298 return t, p, v
298 return t, p, v
299 if i == 5:
299 if i == 5:
300 return v, p, q
300 return v, p, q
301
301
302 golden_ratio = 0.618033988749895
302 golden_ratio = 0.618033988749895
303 h = 0.22717784590367374
303 h = 0.22717784590367374
304
304
305 for _ in xrange(n):
305 for _ in xrange(n):
306 h += golden_ratio
306 h += golden_ratio
307 h %= 1
307 h %= 1
308 HSV_tuple = [h, 0.95, 0.95]
308 HSV_tuple = [h, 0.95, 0.95]
309 RGB_tuple = hsv_to_rgb(*HSV_tuple)
309 RGB_tuple = hsv_to_rgb(*HSV_tuple)
310 yield map(lambda x: str(int(x * 256)), RGB_tuple)
310 yield map(lambda x: str(int(x * 256)), RGB_tuple)
311
311
312 cgenerator = gen_color()
312 cgenerator = gen_color()
313
313
314 def get_color_string(cs):
314 def get_color_string(cs):
315 if cs in color_dict:
315 if cs in color_dict:
316 col = color_dict[cs]
316 col = color_dict[cs]
317 else:
317 else:
318 col = color_dict[cs] = cgenerator.next()
318 col = color_dict[cs] = cgenerator.next()
319 return "color: rgb(%s)! important;" % (', '.join(col))
319 return "color: rgb(%s)! important;" % (', '.join(col))
320
320
321 def url_func(repo_name):
321 def url_func(repo_name):
322
322
323 def _url_func(changeset):
323 def _url_func(changeset):
324 author = changeset.author
324 author = changeset.author
325 date = changeset.date
325 date = changeset.date
326 message = tooltip(changeset.message)
326 message = tooltip(changeset.message)
327
327
328 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
328 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
329 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
329 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
330 "</b> %s<br/></div>")
330 "</b> %s<br/></div>")
331
331
332 tooltip_html = tooltip_html % (author, date, message)
332 tooltip_html = tooltip_html % (author, date, message)
333 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
333 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
334 short_id(changeset.raw_id))
334 short_id(changeset.raw_id))
335 uri = link_to(
335 uri = link_to(
336 lnk_format,
336 lnk_format,
337 url('changeset_home', repo_name=repo_name,
337 url('changeset_home', repo_name=repo_name,
338 revision=changeset.raw_id),
338 revision=changeset.raw_id),
339 style=get_color_string(changeset.raw_id),
339 style=get_color_string(changeset.raw_id),
340 class_='tooltip',
340 class_='tooltip',
341 title=tooltip_html
341 title=tooltip_html
342 )
342 )
343
343
344 uri += '\n'
344 uri += '\n'
345 return uri
345 return uri
346 return _url_func
346 return _url_func
347
347
348 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
348 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
349
349
350
350
351 def is_following_repo(repo_name, user_id):
351 def is_following_repo(repo_name, user_id):
352 from rhodecode.model.scm import ScmModel
352 from rhodecode.model.scm import ScmModel
353 return ScmModel().is_following_repo(repo_name, user_id)
353 return ScmModel().is_following_repo(repo_name, user_id)
354
354
355 flash = _Flash()
355 flash = _Flash()
356
356
357 #==============================================================================
357 #==============================================================================
358 # SCM FILTERS available via h.
358 # SCM FILTERS available via h.
359 #==============================================================================
359 #==============================================================================
360 from rhodecode.lib.vcs.utils import author_name, author_email
360 from rhodecode.lib.vcs.utils import author_name, author_email
361 from rhodecode.lib.utils2 import credentials_filter, age as _age
361 from rhodecode.lib.utils2 import credentials_filter, age as _age
362 from rhodecode.model.db import User, ChangesetStatus
362 from rhodecode.model.db import User, ChangesetStatus
363
363
364 age = lambda x: _age(x)
364 age = lambda x: _age(x)
365 capitalize = lambda x: x.capitalize()
365 capitalize = lambda x: x.capitalize()
366 email = author_email
366 email = author_email
367 short_id = lambda x: x[:12]
367 short_id = lambda x: x[:12]
368 hide_credentials = lambda x: ''.join(credentials_filter(x))
368 hide_credentials = lambda x: ''.join(credentials_filter(x))
369
369
370
370
371 def fmt_date(date):
371 def fmt_date(date):
372 if date:
372 if date:
373 _fmt = _(u"%a, %d %b %Y %H:%M:%S").encode('utf8')
373 _fmt = _(u"%a, %d %b %Y %H:%M:%S").encode('utf8')
374 return date.strftime(_fmt).decode('utf8')
374 return date.strftime(_fmt).decode('utf8')
375
375
376 return ""
376 return ""
377
377
378
378
379 def is_git(repository):
379 def is_git(repository):
380 if hasattr(repository, 'alias'):
380 if hasattr(repository, 'alias'):
381 _type = repository.alias
381 _type = repository.alias
382 elif hasattr(repository, 'repo_type'):
382 elif hasattr(repository, 'repo_type'):
383 _type = repository.repo_type
383 _type = repository.repo_type
384 else:
384 else:
385 _type = repository
385 _type = repository
386 return _type == 'git'
386 return _type == 'git'
387
387
388
388
389 def is_hg(repository):
389 def is_hg(repository):
390 if hasattr(repository, 'alias'):
390 if hasattr(repository, 'alias'):
391 _type = repository.alias
391 _type = repository.alias
392 elif hasattr(repository, 'repo_type'):
392 elif hasattr(repository, 'repo_type'):
393 _type = repository.repo_type
393 _type = repository.repo_type
394 else:
394 else:
395 _type = repository
395 _type = repository
396 return _type == 'hg'
396 return _type == 'hg'
397
397
398
398
399 def email_or_none(author):
399 def email_or_none(author):
400 # extract email from the commit string
400 # extract email from the commit string
401 _email = email(author)
401 _email = email(author)
402 if _email != '':
402 if _email != '':
403 # check it against RhodeCode database, and use the MAIN email for this
403 # check it against RhodeCode database, and use the MAIN email for this
404 # user
404 # user
405 user = User.get_by_email(_email, case_insensitive=True, cache=True)
405 user = User.get_by_email(_email, case_insensitive=True, cache=True)
406 if user is not None:
406 if user is not None:
407 return user.email
407 return user.email
408 return _email
408 return _email
409
409
410 # See if it contains a username we can get an email from
410 # See if it contains a username we can get an email from
411 user = User.get_by_username(author_name(author), case_insensitive=True,
411 user = User.get_by_username(author_name(author), case_insensitive=True,
412 cache=True)
412 cache=True)
413 if user is not None:
413 if user is not None:
414 return user.email
414 return user.email
415
415
416 # No valid email, not a valid user in the system, none!
416 # No valid email, not a valid user in the system, none!
417 return None
417 return None
418
418
419
419
420 def person(author, show_attr="username_and_name"):
420 def person(author, show_attr="username_and_name"):
421 # attr to return from fetched user
421 # attr to return from fetched user
422 person_getter = lambda usr: getattr(usr, show_attr)
422 person_getter = lambda usr: getattr(usr, show_attr)
423
423
424 # Valid email in the attribute passed, see if they're in the system
424 # Valid email in the attribute passed, see if they're in the system
425 _email = email(author)
425 _email = email(author)
426 if _email != '':
426 if _email != '':
427 user = User.get_by_email(_email, case_insensitive=True, cache=True)
427 user = User.get_by_email(_email, case_insensitive=True, cache=True)
428 if user is not None:
428 if user is not None:
429 return person_getter(user)
429 return person_getter(user)
430 return _email
430 return _email
431
431
432 # Maybe it's a username?
432 # Maybe it's a username?
433 _author = author_name(author)
433 _author = author_name(author)
434 user = User.get_by_username(_author, case_insensitive=True,
434 user = User.get_by_username(_author, case_insensitive=True,
435 cache=True)
435 cache=True)
436 if user is not None:
436 if user is not None:
437 return person_getter(user)
437 return person_getter(user)
438
438
439 # Still nothing? Just pass back the author name then
439 # Still nothing? Just pass back the author name then
440 return _author
440 return _author
441
441
442
442
443 def person_by_id(id_, show_attr="username_and_name"):
443 def person_by_id(id_, show_attr="username_and_name"):
444 # attr to return from fetched user
444 # attr to return from fetched user
445 person_getter = lambda usr: getattr(usr, show_attr)
445 person_getter = lambda usr: getattr(usr, show_attr)
446
446
447 #maybe it's an ID ?
447 #maybe it's an ID ?
448 if str(id_).isdigit() or isinstance(id_, int):
448 if str(id_).isdigit() or isinstance(id_, int):
449 id_ = int(id_)
449 id_ = int(id_)
450 user = User.get(id_)
450 user = User.get(id_)
451 if user is not None:
451 if user is not None:
452 return person_getter(user)
452 return person_getter(user)
453 return id_
453 return id_
454
454
455
455
456 def desc_stylize(value):
456 def desc_stylize(value):
457 """
457 """
458 converts tags from value into html equivalent
458 converts tags from value into html equivalent
459
459
460 :param value:
460 :param value:
461 """
461 """
462 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
462 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
463 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
463 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
464 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
464 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
465 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
465 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
466 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z\-\/]*)\]',
466 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z\-\/]*)\]',
467 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
467 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
468 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/]*)\]',
468 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/]*)\]',
469 '<div class="metatag" tag="lang">\\2</div>', value)
469 '<div class="metatag" tag="lang">\\2</div>', value)
470 value = re.sub(r'\[([a-z]+)\]',
470 value = re.sub(r'\[([a-z]+)\]',
471 '<div class="metatag" tag="\\1">\\1</div>', value)
471 '<div class="metatag" tag="\\1">\\1</div>', value)
472
472
473 return value
473 return value
474
474
475
475
476 def bool2icon(value):
476 def bool2icon(value):
477 """Returns True/False values represented as small html image of true/false
477 """Returns True/False values represented as small html image of true/false
478 icons
478 icons
479
479
480 :param value: bool value
480 :param value: bool value
481 """
481 """
482
482
483 if value is True:
483 if value is True:
484 return HTML.tag('img', src=url("/images/icons/accept.png"),
484 return HTML.tag('img', src=url("/images/icons/accept.png"),
485 alt=_('True'))
485 alt=_('True'))
486
486
487 if value is False:
487 if value is False:
488 return HTML.tag('img', src=url("/images/icons/cancel.png"),
488 return HTML.tag('img', src=url("/images/icons/cancel.png"),
489 alt=_('False'))
489 alt=_('False'))
490
490
491 return value
491 return value
492
492
493
493
494 def action_parser(user_log, feed=False):
494 def action_parser(user_log, feed=False):
495 """
495 """
496 This helper will action_map the specified string action into translated
496 This helper will action_map the specified string action into translated
497 fancy names with icons and links
497 fancy names with icons and links
498
498
499 :param user_log: user log instance
499 :param user_log: user log instance
500 :param feed: use output for feeds (no html and fancy icons)
500 :param feed: use output for feeds (no html and fancy icons)
501 """
501 """
502
502
503 action = user_log.action
503 action = user_log.action
504 action_params = ' '
504 action_params = ' '
505
505
506 x = action.split(':')
506 x = action.split(':')
507
507
508 if len(x) > 1:
508 if len(x) > 1:
509 action, action_params = x
509 action, action_params = x
510
510
511 def get_cs_links():
511 def get_cs_links():
512 revs_limit = 3 # display this amount always
512 revs_limit = 3 # display this amount always
513 revs_top_limit = 50 # show upto this amount of changesets hidden
513 revs_top_limit = 50 # show upto this amount of changesets hidden
514 revs_ids = action_params.split(',')
514 revs_ids = action_params.split(',')
515 deleted = user_log.repository is None
515 deleted = user_log.repository is None
516 if deleted:
516 if deleted:
517 return ','.join(revs_ids)
517 return ','.join(revs_ids)
518
518
519 repo_name = user_log.repository.repo_name
519 repo_name = user_log.repository.repo_name
520
520
521 repo = user_log.repository.scm_instance
521 repo = user_log.repository.scm_instance
522
522
523 def lnk(rev, repo_name):
523 def lnk(rev, repo_name):
524
524
525 if isinstance(rev, BaseChangeset):
525 if isinstance(rev, BaseChangeset):
526 lbl = 'r%s:%s' % (rev.revision, rev.short_id)
526 lbl = 'r%s:%s' % (rev.revision, rev.short_id)
527 _url = url('changeset_home', repo_name=repo_name,
527 _url = url('changeset_home', repo_name=repo_name,
528 revision=rev.raw_id)
528 revision=rev.raw_id)
529 title = tooltip(rev.message)
529 title = tooltip(rev.message)
530 else:
530 else:
531 lbl = '%s' % rev
531 lbl = '%s' % rev
532 _url = '#'
532 _url = '#'
533 title = _('Changeset not found')
533 title = _('Changeset not found')
534
534
535 return link_to(lbl, _url, title=title, class_='tooltip',)
535 return link_to(lbl, _url, title=title, class_='tooltip',)
536
536
537 revs = []
537 revs = []
538 if len(filter(lambda v: v != '', revs_ids)) > 0:
538 if len(filter(lambda v: v != '', revs_ids)) > 0:
539 for rev in revs_ids[:revs_top_limit]:
539 for rev in revs_ids[:revs_top_limit]:
540 try:
540 try:
541 rev = repo.get_changeset(rev)
541 rev = repo.get_changeset(rev)
542 revs.append(rev)
542 revs.append(rev)
543 except ChangesetDoesNotExistError:
543 except ChangesetDoesNotExistError:
544 log.error('cannot find revision %s in this repo' % rev)
544 log.error('cannot find revision %s in this repo' % rev)
545 revs.append(rev)
545 revs.append(rev)
546 continue
546 continue
547 cs_links = []
547 cs_links = []
548 cs_links.append(" " + ', '.join(
548 cs_links.append(" " + ', '.join(
549 [lnk(rev, repo_name) for rev in revs[:revs_limit]]
549 [lnk(rev, repo_name) for rev in revs[:revs_limit]]
550 )
550 )
551 )
551 )
552
552
553 compare_view = (
553 compare_view = (
554 ' <div class="compare_view tooltip" title="%s">'
554 ' <div class="compare_view tooltip" title="%s">'
555 '<a href="%s">%s</a> </div>' % (
555 '<a href="%s">%s</a> </div>' % (
556 _('Show all combined changesets %s->%s') % (
556 _('Show all combined changesets %s->%s') % (
557 revs_ids[0], revs_ids[-1]
557 revs_ids[0], revs_ids[-1]
558 ),
558 ),
559 url('changeset_home', repo_name=repo_name,
559 url('changeset_home', repo_name=repo_name,
560 revision='%s...%s' % (revs_ids[0], revs_ids[-1])
560 revision='%s...%s' % (revs_ids[0], revs_ids[-1])
561 ),
561 ),
562 _('compare view')
562 _('compare view')
563 )
563 )
564 )
564 )
565
565
566 # if we have exactly one more than normally displayed
566 # if we have exactly one more than normally displayed
567 # just display it, takes less space than displaying
567 # just display it, takes less space than displaying
568 # "and 1 more revisions"
568 # "and 1 more revisions"
569 if len(revs_ids) == revs_limit + 1:
569 if len(revs_ids) == revs_limit + 1:
570 rev = revs[revs_limit]
570 rev = revs[revs_limit]
571 cs_links.append(", " + lnk(rev, repo_name))
571 cs_links.append(", " + lnk(rev, repo_name))
572
572
573 # hidden-by-default ones
573 # hidden-by-default ones
574 if len(revs_ids) > revs_limit + 1:
574 if len(revs_ids) > revs_limit + 1:
575 uniq_id = revs_ids[0]
575 uniq_id = revs_ids[0]
576 html_tmpl = (
576 html_tmpl = (
577 '<span> %s <a class="show_more" id="_%s" '
577 '<span> %s <a class="show_more" id="_%s" '
578 'href="#more">%s</a> %s</span>'
578 'href="#more">%s</a> %s</span>'
579 )
579 )
580 if not feed:
580 if not feed:
581 cs_links.append(html_tmpl % (
581 cs_links.append(html_tmpl % (
582 _('and'),
582 _('and'),
583 uniq_id, _('%s more') % (len(revs_ids) - revs_limit),
583 uniq_id, _('%s more') % (len(revs_ids) - revs_limit),
584 _('revisions')
584 _('revisions')
585 )
585 )
586 )
586 )
587
587
588 if not feed:
588 if not feed:
589 html_tmpl = '<span id="%s" style="display:none">, %s </span>'
589 html_tmpl = '<span id="%s" style="display:none">, %s </span>'
590 else:
590 else:
591 html_tmpl = '<span id="%s"> %s </span>'
591 html_tmpl = '<span id="%s"> %s </span>'
592
592
593 morelinks = ', '.join(
593 morelinks = ', '.join(
594 [lnk(rev, repo_name) for rev in revs[revs_limit:]]
594 [lnk(rev, repo_name) for rev in revs[revs_limit:]]
595 )
595 )
596
596
597 if len(revs_ids) > revs_top_limit:
597 if len(revs_ids) > revs_top_limit:
598 morelinks += ', ...'
598 morelinks += ', ...'
599
599
600 cs_links.append(html_tmpl % (uniq_id, morelinks))
600 cs_links.append(html_tmpl % (uniq_id, morelinks))
601 if len(revs) > 1:
601 if len(revs) > 1:
602 cs_links.append(compare_view)
602 cs_links.append(compare_view)
603 return ''.join(cs_links)
603 return ''.join(cs_links)
604
604
605 def get_fork_name():
605 def get_fork_name():
606 repo_name = action_params
606 repo_name = action_params
607 return _('fork name ') + str(link_to(action_params, url('summary_home',
607 return _('fork name ') + str(link_to(action_params, url('summary_home',
608 repo_name=repo_name,)))
608 repo_name=repo_name,)))
609
609
610 def get_user_name():
610 def get_user_name():
611 user_name = action_params
611 user_name = action_params
612 return user_name
612 return user_name
613
613
614 def get_users_group():
614 def get_users_group():
615 group_name = action_params
615 group_name = action_params
616 return group_name
616 return group_name
617
617
618 def get_pull_request():
618 def get_pull_request():
619 pull_request_id = action_params
619 pull_request_id = action_params
620 repo_name = user_log.repository.repo_name
620 repo_name = user_log.repository.repo_name
621 return link_to(_('Pull request #%s') % pull_request_id,
621 return link_to(_('Pull request #%s') % pull_request_id,
622 url('pullrequest_show', repo_name=repo_name,
622 url('pullrequest_show', repo_name=repo_name,
623 pull_request_id=pull_request_id))
623 pull_request_id=pull_request_id))
624
624
625 # action : translated str, callback(extractor), icon
625 # action : translated str, callback(extractor), icon
626 action_map = {
626 action_map = {
627 'user_deleted_repo': (_('[deleted] repository'),
627 'user_deleted_repo': (_('[deleted] repository'),
628 None, 'database_delete.png'),
628 None, 'database_delete.png'),
629 'user_created_repo': (_('[created] repository'),
629 'user_created_repo': (_('[created] repository'),
630 None, 'database_add.png'),
630 None, 'database_add.png'),
631 'user_created_fork': (_('[created] repository as fork'),
631 'user_created_fork': (_('[created] repository as fork'),
632 None, 'arrow_divide.png'),
632 None, 'arrow_divide.png'),
633 'user_forked_repo': (_('[forked] repository'),
633 'user_forked_repo': (_('[forked] repository'),
634 get_fork_name, 'arrow_divide.png'),
634 get_fork_name, 'arrow_divide.png'),
635 'user_updated_repo': (_('[updated] repository'),
635 'user_updated_repo': (_('[updated] repository'),
636 None, 'database_edit.png'),
636 None, 'database_edit.png'),
637 'admin_deleted_repo': (_('[delete] repository'),
637 'admin_deleted_repo': (_('[delete] repository'),
638 None, 'database_delete.png'),
638 None, 'database_delete.png'),
639 'admin_created_repo': (_('[created] repository'),
639 'admin_created_repo': (_('[created] repository'),
640 None, 'database_add.png'),
640 None, 'database_add.png'),
641 'admin_forked_repo': (_('[forked] repository'),
641 'admin_forked_repo': (_('[forked] repository'),
642 None, 'arrow_divide.png'),
642 None, 'arrow_divide.png'),
643 'admin_updated_repo': (_('[updated] repository'),
643 'admin_updated_repo': (_('[updated] repository'),
644 None, 'database_edit.png'),
644 None, 'database_edit.png'),
645 'admin_created_user': (_('[created] user'),
645 'admin_created_user': (_('[created] user'),
646 get_user_name, 'user_add.png'),
646 get_user_name, 'user_add.png'),
647 'admin_updated_user': (_('[updated] user'),
647 'admin_updated_user': (_('[updated] user'),
648 get_user_name, 'user_edit.png'),
648 get_user_name, 'user_edit.png'),
649 'admin_created_users_group': (_('[created] users group'),
649 'admin_created_users_group': (_('[created] users group'),
650 get_users_group, 'group_add.png'),
650 get_users_group, 'group_add.png'),
651 'admin_updated_users_group': (_('[updated] users group'),
651 'admin_updated_users_group': (_('[updated] users group'),
652 get_users_group, 'group_edit.png'),
652 get_users_group, 'group_edit.png'),
653 'user_commented_revision': (_('[commented] on revision in repository'),
653 'user_commented_revision': (_('[commented] on revision in repository'),
654 get_cs_links, 'comment_add.png'),
654 get_cs_links, 'comment_add.png'),
655 'user_commented_pull_request': (_('[commented] on pull request for'),
655 'user_commented_pull_request': (_('[commented] on pull request for'),
656 get_pull_request, 'comment_add.png'),
656 get_pull_request, 'comment_add.png'),
657 'user_closed_pull_request': (_('[closed] pull request for'),
657 'user_closed_pull_request': (_('[closed] pull request for'),
658 get_pull_request, 'tick.png'),
658 get_pull_request, 'tick.png'),
659 'push': (_('[pushed] into'),
659 'push': (_('[pushed] into'),
660 get_cs_links, 'script_add.png'),
660 get_cs_links, 'script_add.png'),
661 'push_local': (_('[committed via RhodeCode] into repository'),
661 'push_local': (_('[committed via RhodeCode] into repository'),
662 get_cs_links, 'script_edit.png'),
662 get_cs_links, 'script_edit.png'),
663 'push_remote': (_('[pulled from remote] into repository'),
663 'push_remote': (_('[pulled from remote] into repository'),
664 get_cs_links, 'connect.png'),
664 get_cs_links, 'connect.png'),
665 'pull': (_('[pulled] from'),
665 'pull': (_('[pulled] from'),
666 None, 'down_16.png'),
666 None, 'down_16.png'),
667 'started_following_repo': (_('[started following] repository'),
667 'started_following_repo': (_('[started following] repository'),
668 None, 'heart_add.png'),
668 None, 'heart_add.png'),
669 'stopped_following_repo': (_('[stopped following] repository'),
669 'stopped_following_repo': (_('[stopped following] repository'),
670 None, 'heart_delete.png'),
670 None, 'heart_delete.png'),
671 }
671 }
672
672
673 action_str = action_map.get(action, action)
673 action_str = action_map.get(action, action)
674 if feed:
674 if feed:
675 action = action_str[0].replace('[', '').replace(']', '')
675 action = action_str[0].replace('[', '').replace(']', '')
676 else:
676 else:
677 action = action_str[0]\
677 action = action_str[0]\
678 .replace('[', '<span class="journal_highlight">')\
678 .replace('[', '<span class="journal_highlight">')\
679 .replace(']', '</span>')
679 .replace(']', '</span>')
680
680
681 action_params_func = lambda: ""
681 action_params_func = lambda: ""
682
682
683 if callable(action_str[1]):
683 if callable(action_str[1]):
684 action_params_func = action_str[1]
684 action_params_func = action_str[1]
685
685
686 def action_parser_icon():
686 def action_parser_icon():
687 action = user_log.action
687 action = user_log.action
688 action_params = None
688 action_params = None
689 x = action.split(':')
689 x = action.split(':')
690
690
691 if len(x) > 1:
691 if len(x) > 1:
692 action, action_params = x
692 action, action_params = x
693
693
694 tmpl = """<img src="%s%s" alt="%s"/>"""
694 tmpl = """<img src="%s%s" alt="%s"/>"""
695 ico = action_map.get(action, ['', '', ''])[2]
695 ico = action_map.get(action, ['', '', ''])[2]
696 return literal(tmpl % ((url('/images/icons/')), ico, action))
696 return literal(tmpl % ((url('/images/icons/')), ico, action))
697
697
698 # returned callbacks we need to call to get
698 # returned callbacks we need to call to get
699 return [lambda: literal(action), action_params_func, action_parser_icon]
699 return [lambda: literal(action), action_params_func, action_parser_icon]
700
700
701
701
702
702
703 #==============================================================================
703 #==============================================================================
704 # PERMS
704 # PERMS
705 #==============================================================================
705 #==============================================================================
706 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
706 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
707 HasRepoPermissionAny, HasRepoPermissionAll
707 HasRepoPermissionAny, HasRepoPermissionAll
708
708
709
709
710 #==============================================================================
710 #==============================================================================
711 # GRAVATAR URL
711 # GRAVATAR URL
712 #==============================================================================
712 #==============================================================================
713
713
714 def gravatar_url(email_address, size=30):
714 def gravatar_url(email_address, size=30):
715 from pylons import url ## doh, we need to re-import url to mock it later
715 from pylons import url ## doh, we need to re-import url to mock it later
716 if(str2bool(config['app_conf'].get('use_gravatar')) and
716 if(str2bool(config['app_conf'].get('use_gravatar')) and
717 config['app_conf'].get('alternative_gravatar_url')):
717 config['app_conf'].get('alternative_gravatar_url')):
718 tmpl = config['app_conf'].get('alternative_gravatar_url', '')
718 tmpl = config['app_conf'].get('alternative_gravatar_url', '')
719 parsed_url = urlparse.urlparse(url.current(qualified=True))
719 parsed_url = urlparse.urlparse(url.current(qualified=True))
720 tmpl = tmpl.replace('{email}', email_address)\
720 tmpl = tmpl.replace('{email}', email_address)\
721 .replace('{md5email}', hashlib.md5(email_address.lower()).hexdigest()) \
721 .replace('{md5email}', hashlib.md5(email_address.lower()).hexdigest()) \
722 .replace('{netloc}', parsed_url.netloc)\
722 .replace('{netloc}', parsed_url.netloc)\
723 .replace('{scheme}', parsed_url.scheme)\
723 .replace('{scheme}', parsed_url.scheme)\
724 .replace('{size}', str(size))
724 .replace('{size}', str(size))
725 return tmpl
725 return tmpl
726
726
727 if (not str2bool(config['app_conf'].get('use_gravatar')) or
727 if (not str2bool(config['app_conf'].get('use_gravatar')) or
728 not email_address or email_address == 'anonymous@rhodecode.org'):
728 not email_address or email_address == 'anonymous@rhodecode.org'):
729 f = lambda a, l: min(l, key=lambda x: abs(x - a))
729 f = lambda a, l: min(l, key=lambda x: abs(x - a))
730 return url("/images/user%s.png" % f(size, [14, 16, 20, 24, 30]))
730 return url("/images/user%s.png" % f(size, [14, 16, 20, 24, 30]))
731
731
732 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
732 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
733 default = 'identicon'
733 default = 'identicon'
734 baseurl_nossl = "http://www.gravatar.com/avatar/"
734 baseurl_nossl = "http://www.gravatar.com/avatar/"
735 baseurl_ssl = "https://secure.gravatar.com/avatar/"
735 baseurl_ssl = "https://secure.gravatar.com/avatar/"
736 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
736 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
737
737
738 if isinstance(email_address, unicode):
738 if isinstance(email_address, unicode):
739 #hashlib crashes on unicode items
739 #hashlib crashes on unicode items
740 email_address = safe_str(email_address)
740 email_address = safe_str(email_address)
741 # construct the url
741 # construct the url
742 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
742 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
743 gravatar_url += urllib.urlencode({'d': default, 's': str(size)})
743 gravatar_url += urllib.urlencode({'d': default, 's': str(size)})
744
744
745 return gravatar_url
745 return gravatar_url
746
746
747
747
748 #==============================================================================
748 #==============================================================================
749 # REPO PAGER, PAGER FOR REPOSITORY
749 # REPO PAGER, PAGER FOR REPOSITORY
750 #==============================================================================
750 #==============================================================================
751 class RepoPage(Page):
751 class RepoPage(Page):
752
752
753 def __init__(self, collection, page=1, items_per_page=20,
753 def __init__(self, collection, page=1, items_per_page=20,
754 item_count=None, url=None, **kwargs):
754 item_count=None, url=None, **kwargs):
755
755
756 """Create a "RepoPage" instance. special pager for paging
756 """Create a "RepoPage" instance. special pager for paging
757 repository
757 repository
758 """
758 """
759 self._url_generator = url
759 self._url_generator = url
760
760
761 # Safe the kwargs class-wide so they can be used in the pager() method
761 # Safe the kwargs class-wide so they can be used in the pager() method
762 self.kwargs = kwargs
762 self.kwargs = kwargs
763
763
764 # Save a reference to the collection
764 # Save a reference to the collection
765 self.original_collection = collection
765 self.original_collection = collection
766
766
767 self.collection = collection
767 self.collection = collection
768
768
769 # The self.page is the number of the current page.
769 # The self.page is the number of the current page.
770 # The first page has the number 1!
770 # The first page has the number 1!
771 try:
771 try:
772 self.page = int(page) # make it int() if we get it as a string
772 self.page = int(page) # make it int() if we get it as a string
773 except (ValueError, TypeError):
773 except (ValueError, TypeError):
774 self.page = 1
774 self.page = 1
775
775
776 self.items_per_page = items_per_page
776 self.items_per_page = items_per_page
777
777
778 # Unless the user tells us how many items the collections has
778 # Unless the user tells us how many items the collections has
779 # we calculate that ourselves.
779 # we calculate that ourselves.
780 if item_count is not None:
780 if item_count is not None:
781 self.item_count = item_count
781 self.item_count = item_count
782 else:
782 else:
783 self.item_count = len(self.collection)
783 self.item_count = len(self.collection)
784
784
785 # Compute the number of the first and last available page
785 # Compute the number of the first and last available page
786 if self.item_count > 0:
786 if self.item_count > 0:
787 self.first_page = 1
787 self.first_page = 1
788 self.page_count = int(math.ceil(float(self.item_count) /
788 self.page_count = int(math.ceil(float(self.item_count) /
789 self.items_per_page))
789 self.items_per_page))
790 self.last_page = self.first_page + self.page_count - 1
790 self.last_page = self.first_page + self.page_count - 1
791
791
792 # Make sure that the requested page number is the range of
792 # Make sure that the requested page number is the range of
793 # valid pages
793 # valid pages
794 if self.page > self.last_page:
794 if self.page > self.last_page:
795 self.page = self.last_page
795 self.page = self.last_page
796 elif self.page < self.first_page:
796 elif self.page < self.first_page:
797 self.page = self.first_page
797 self.page = self.first_page
798
798
799 # Note: the number of items on this page can be less than
799 # Note: the number of items on this page can be less than
800 # items_per_page if the last page is not full
800 # items_per_page if the last page is not full
801 self.first_item = max(0, (self.item_count) - (self.page *
801 self.first_item = max(0, (self.item_count) - (self.page *
802 items_per_page))
802 items_per_page))
803 self.last_item = ((self.item_count - 1) - items_per_page *
803 self.last_item = ((self.item_count - 1) - items_per_page *
804 (self.page - 1))
804 (self.page - 1))
805
805
806 self.items = list(self.collection[self.first_item:self.last_item + 1])
806 self.items = list(self.collection[self.first_item:self.last_item + 1])
807
807
808 # Links to previous and next page
808 # Links to previous and next page
809 if self.page > self.first_page:
809 if self.page > self.first_page:
810 self.previous_page = self.page - 1
810 self.previous_page = self.page - 1
811 else:
811 else:
812 self.previous_page = None
812 self.previous_page = None
813
813
814 if self.page < self.last_page:
814 if self.page < self.last_page:
815 self.next_page = self.page + 1
815 self.next_page = self.page + 1
816 else:
816 else:
817 self.next_page = None
817 self.next_page = None
818
818
819 # No items available
819 # No items available
820 else:
820 else:
821 self.first_page = None
821 self.first_page = None
822 self.page_count = 0
822 self.page_count = 0
823 self.last_page = None
823 self.last_page = None
824 self.first_item = None
824 self.first_item = None
825 self.last_item = None
825 self.last_item = None
826 self.previous_page = None
826 self.previous_page = None
827 self.next_page = None
827 self.next_page = None
828 self.items = []
828 self.items = []
829
829
830 # This is a subclass of the 'list' type. Initialise the list now.
830 # This is a subclass of the 'list' type. Initialise the list now.
831 list.__init__(self, reversed(self.items))
831 list.__init__(self, reversed(self.items))
832
832
833
833
834 def changed_tooltip(nodes):
834 def changed_tooltip(nodes):
835 """
835 """
836 Generates a html string for changed nodes in changeset page.
836 Generates a html string for changed nodes in changeset page.
837 It limits the output to 30 entries
837 It limits the output to 30 entries
838
838
839 :param nodes: LazyNodesGenerator
839 :param nodes: LazyNodesGenerator
840 """
840 """
841 if nodes:
841 if nodes:
842 pref = ': <br/> '
842 pref = ': <br/> '
843 suf = ''
843 suf = ''
844 if len(nodes) > 30:
844 if len(nodes) > 30:
845 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
845 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
846 return literal(pref + '<br/> '.join([safe_unicode(x.path)
846 return literal(pref + '<br/> '.join([safe_unicode(x.path)
847 for x in nodes[:30]]) + suf)
847 for x in nodes[:30]]) + suf)
848 else:
848 else:
849 return ': ' + _('No Files')
849 return ': ' + _('No Files')
850
850
851
851
852 def repo_link(groups_and_repos):
852 def repo_link(groups_and_repos):
853 """
853 """
854 Makes a breadcrumbs link to repo within a group
854 Makes a breadcrumbs link to repo within a group
855 joins &raquo; on each group to create a fancy link
855 joins &raquo; on each group to create a fancy link
856
856
857 ex::
857 ex::
858 group >> subgroup >> repo
858 group >> subgroup >> repo
859
859
860 :param groups_and_repos:
860 :param groups_and_repos:
861 """
861 """
862 groups, repo_name = groups_and_repos
862 groups, repo_name = groups_and_repos
863
863
864 if not groups:
864 if not groups:
865 return repo_name
865 return repo_name
866 else:
866 else:
867 def make_link(group):
867 def make_link(group):
868 return link_to(group.name, url('repos_group_home',
868 return link_to(group.name, url('repos_group_home',
869 group_name=group.group_name))
869 group_name=group.group_name))
870 return literal(' &raquo; '.join(map(make_link, groups)) + \
870 return literal(' &raquo; '.join(map(make_link, groups)) + \
871 " &raquo; " + repo_name)
871 " &raquo; " + repo_name)
872
872
873
873
874 def fancy_file_stats(stats):
874 def fancy_file_stats(stats):
875 """
875 """
876 Displays a fancy two colored bar for number of added/deleted
876 Displays a fancy two colored bar for number of added/deleted
877 lines of code on file
877 lines of code on file
878
878
879 :param stats: two element list of added/deleted lines of code
879 :param stats: two element list of added/deleted lines of code
880 """
880 """
881
881
882 a, d, t = stats[0], stats[1], stats[0] + stats[1]
882 a, d, t = stats[0], stats[1], stats[0] + stats[1]
883 width = 100
883 width = 100
884 unit = float(width) / (t or 1)
884 unit = float(width) / (t or 1)
885
885
886 # needs > 9% of width to be visible or 0 to be hidden
886 # needs > 9% of width to be visible or 0 to be hidden
887 a_p = max(9, unit * a) if a > 0 else 0
887 a_p = max(9, unit * a) if a > 0 else 0
888 d_p = max(9, unit * d) if d > 0 else 0
888 d_p = max(9, unit * d) if d > 0 else 0
889 p_sum = a_p + d_p
889 p_sum = a_p + d_p
890
890
891 if p_sum > width:
891 if p_sum > width:
892 #adjust the percentage to be == 100% since we adjusted to 9
892 #adjust the percentage to be == 100% since we adjusted to 9
893 if a_p > d_p:
893 if a_p > d_p:
894 a_p = a_p - (p_sum - width)
894 a_p = a_p - (p_sum - width)
895 else:
895 else:
896 d_p = d_p - (p_sum - width)
896 d_p = d_p - (p_sum - width)
897
897
898 a_v = a if a > 0 else ''
898 a_v = a if a > 0 else ''
899 d_v = d if d > 0 else ''
899 d_v = d if d > 0 else ''
900
900
901 def cgen(l_type):
901 def cgen(l_type):
902 mapping = {'tr': 'top-right-rounded-corner-mid',
902 mapping = {'tr': 'top-right-rounded-corner-mid',
903 'tl': 'top-left-rounded-corner-mid',
903 'tl': 'top-left-rounded-corner-mid',
904 'br': 'bottom-right-rounded-corner-mid',
904 'br': 'bottom-right-rounded-corner-mid',
905 'bl': 'bottom-left-rounded-corner-mid'}
905 'bl': 'bottom-left-rounded-corner-mid'}
906 map_getter = lambda x: mapping[x]
906 map_getter = lambda x: mapping[x]
907
907
908 if l_type == 'a' and d_v:
908 if l_type == 'a' and d_v:
909 #case when added and deleted are present
909 #case when added and deleted are present
910 return ' '.join(map(map_getter, ['tl', 'bl']))
910 return ' '.join(map(map_getter, ['tl', 'bl']))
911
911
912 if l_type == 'a' and not d_v:
912 if l_type == 'a' and not d_v:
913 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
913 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
914
914
915 if l_type == 'd' and a_v:
915 if l_type == 'd' and a_v:
916 return ' '.join(map(map_getter, ['tr', 'br']))
916 return ' '.join(map(map_getter, ['tr', 'br']))
917
917
918 if l_type == 'd' and not a_v:
918 if l_type == 'd' and not a_v:
919 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
919 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
920
920
921 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
921 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
922 cgen('a'), a_p, a_v
922 cgen('a'), a_p, a_v
923 )
923 )
924 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
924 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
925 cgen('d'), d_p, d_v
925 cgen('d'), d_p, d_v
926 )
926 )
927 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
927 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
928
928
929
929
930 def urlify_text(text_):
930 def urlify_text(text_):
931 import re
931 import re
932
932
933 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
933 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
934 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
934 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
935
935
936 def url_func(match_obj):
936 def url_func(match_obj):
937 url_full = match_obj.groups()[0]
937 url_full = match_obj.groups()[0]
938 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
938 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
939
939
940 return literal(url_pat.sub(url_func, text_))
940 return literal(url_pat.sub(url_func, text_))
941
941
942
942
943 def urlify_changesets(text_, repository):
943 def urlify_changesets(text_, repository):
944 """
944 """
945 Extract revision ids from changeset and make link from them
945 Extract revision ids from changeset and make link from them
946
946
947 :param text_:
947 :param text_:
948 :param repository:
948 :param repository:
949 """
949 """
950 import re
950 import re
951 URL_PAT = re.compile(r'([0-9a-fA-F]{12,})')
951 URL_PAT = re.compile(r'([0-9a-fA-F]{12,})')
952
952
953 def url_func(match_obj):
953 def url_func(match_obj):
954 rev = match_obj.groups()[0]
954 rev = match_obj.groups()[0]
955 pref = ''
955 pref = ''
956 if match_obj.group().startswith(' '):
956 if match_obj.group().startswith(' '):
957 pref = ' '
957 pref = ' '
958 tmpl = (
958 tmpl = (
959 '%(pref)s<a class="%(cls)s" href="%(url)s">'
959 '%(pref)s<a class="%(cls)s" href="%(url)s">'
960 '%(rev)s'
960 '%(rev)s'
961 '</a>'
961 '</a>'
962 )
962 )
963 return tmpl % {
963 return tmpl % {
964 'pref': pref,
964 'pref': pref,
965 'cls': 'revision-link',
965 'cls': 'revision-link',
966 'url': url('changeset_home', repo_name=repository, revision=rev),
966 'url': url('changeset_home', repo_name=repository, revision=rev),
967 'rev': rev,
967 'rev': rev,
968 }
968 }
969
969
970 newtext = URL_PAT.sub(url_func, text_)
970 newtext = URL_PAT.sub(url_func, text_)
971
971
972 return newtext
972 return newtext
973
973
974
974
975 def urlify_commit(text_, repository=None, link_=None):
975 def urlify_commit(text_, repository=None, link_=None):
976 """
976 """
977 Parses given text message and makes proper links.
977 Parses given text message and makes proper links.
978 issues are linked to given issue-server, and rest is a changeset link
978 issues are linked to given issue-server, and rest is a changeset link
979 if link_ is given, in other case it's a plain text
979 if link_ is given, in other case it's a plain text
980
980
981 :param text_:
981 :param text_:
982 :param repository:
982 :param repository:
983 :param link_: changeset link
983 :param link_: changeset link
984 """
984 """
985 import re
985 import re
986 import traceback
986 import traceback
987
987
988 def escaper(string):
988 def escaper(string):
989 return string.replace('<', '&lt;').replace('>', '&gt;')
989 return string.replace('<', '&lt;').replace('>', '&gt;')
990
990
991 def linkify_others(t, l):
991 def linkify_others(t, l):
992 urls = re.compile(r'(\<a.*?\<\/a\>)',)
992 urls = re.compile(r'(\<a.*?\<\/a\>)',)
993 links = []
993 links = []
994 for e in urls.split(t):
994 for e in urls.split(t):
995 if not urls.match(e):
995 if not urls.match(e):
996 links.append('<a class="message-link" href="%s">%s</a>' % (l, e))
996 links.append('<a class="message-link" href="%s">%s</a>' % (l, e))
997 else:
997 else:
998 links.append(e)
998 links.append(e)
999
999
1000 return ''.join(links)
1000 return ''.join(links)
1001
1001
1002 # urlify changesets - extrac revisions and make link out of them
1002 # urlify changesets - extrac revisions and make link out of them
1003 newtext = urlify_changesets(escaper(text_), repository)
1003 newtext = urlify_changesets(escaper(text_), repository)
1004
1004
1005 try:
1005 try:
1006 conf = config['app_conf']
1006 conf = config['app_conf']
1007
1007
1008 # allow multiple issue servers to be used
1008 # allow multiple issue servers to be used
1009 valid_indices = [
1009 valid_indices = [
1010 x.group(1)
1010 x.group(1)
1011 for x in map(lambda x: re.match(r'issue_pat(.*)', x), conf.keys())
1011 for x in map(lambda x: re.match(r'issue_pat(.*)', x), conf.keys())
1012 if x and conf.has_key('issue_server_link'+x.group(1)) and conf.has_key('issue_prefix'+x.group(1))
1012 if x and 'issue_server_link%s' % x.group(1) in conf
1013 ]
1013 and 'issue_prefix%s' % x.group(1) in conf
1014 ]
1014
1015
1015 #log.debug('found issue server suffixes ' + ','.join(valid_indices) + ' during valuation of: \n' + newtext)
1016 log.debug('found issue server suffixes `%s` during valuation of: %s'
1017 % (','.join(valid_indices), newtext))
1016
1018
1017 for pattern_index in valid_indices:
1019 for pattern_index in valid_indices:
1018 ISSUE_PATTERN = conf.get('issue_pat'+pattern_index)
1020 ISSUE_PATTERN = conf.get('issue_pat%s' % pattern_index)
1019 ISSUE_SERVER_LNK = conf.get('issue_server_link'+pattern_index)
1021 ISSUE_SERVER_LNK = conf.get('issue_server_link%s' % pattern_index)
1020 ISSUE_PREFIX = conf.get('issue_prefix'+pattern_index)
1022 ISSUE_PREFIX = conf.get('issue_prefix%s' % pattern_index)
1021
1023
1022 #log.debug(ISSUE_PATTERN + ' ' + ISSUE_SERVER_LNK + ' ' + ISSUE_PREFIX)
1024 log.debug('pattern suffix `%s` PAT:%s SERVER_LINK:%s PREFIX:%s'
1025 % (pattern_index, ISSUE_PATTERN, ISSUE_SERVER_LNK,
1026 ISSUE_PREFIX))
1023
1027
1024 URL_PAT = re.compile(r'%s' % ISSUE_PATTERN)
1028 URL_PAT = re.compile(r'%s' % ISSUE_PATTERN)
1025
1029
1026 def url_func(match_obj):
1030 def url_func(match_obj):
1027 pref = ''
1031 pref = ''
1028 if match_obj.group().startswith(' '):
1032 if match_obj.group().startswith(' '):
1029 pref = ' '
1033 pref = ' '
1030
1034
1031 issue_id = ''.join(match_obj.groups())
1035 issue_id = ''.join(match_obj.groups())
1032 tmpl = (
1036 tmpl = (
1033 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1037 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1034 '%(issue-prefix)s%(id-repr)s'
1038 '%(issue-prefix)s%(id-repr)s'
1035 '</a>'
1039 '</a>'
1036 )
1040 )
1037 url = ISSUE_SERVER_LNK.replace('{id}', issue_id)
1041 url = ISSUE_SERVER_LNK.replace('{id}', issue_id)
1038 if repository:
1042 if repository:
1039 url = url.replace('{repo}', repository)
1043 url = url.replace('{repo}', repository)
1040 repo_name = repository.split(URL_SEP)[-1]
1044 repo_name = repository.split(URL_SEP)[-1]
1041 url = url.replace('{repo_name}', repo_name)
1045 url = url.replace('{repo_name}', repo_name)
1042
1046
1043 return tmpl % {
1047 return tmpl % {
1044 'pref': pref,
1048 'pref': pref,
1045 'cls': 'issue-tracker-link',
1049 'cls': 'issue-tracker-link',
1046 'url': url,
1050 'url': url,
1047 'id-repr': issue_id,
1051 'id-repr': issue_id,
1048 'issue-prefix': ISSUE_PREFIX,
1052 'issue-prefix': ISSUE_PREFIX,
1049 'serv': ISSUE_SERVER_LNK,
1053 'serv': ISSUE_SERVER_LNK,
1050 }
1054 }
1051
1052 newtext = URL_PAT.sub(url_func, newtext)
1055 newtext = URL_PAT.sub(url_func, newtext)
1053 #log.debug('after '+pattern_index+':\n'+newtext)
1056 log.debug('processed prefix:`%s` => %s' % (pattern_index, newtext))
1054
1057
1055 # if we actually did something above
1058 # if we actually did something above
1056 if valid_indices:
1059 if valid_indices:
1057 if link_:
1060 if link_:
1058 # wrap not links into final link => link_
1061 # wrap not links into final link => link_
1059 newtext = linkify_others(newtext, link_)
1062 newtext = linkify_others(newtext, link_)
1060
1063
1061 return literal(newtext)
1064 return literal(newtext)
1062 except:
1065 except:
1063 log.error(traceback.format_exc())
1066 log.error(traceback.format_exc())
1064 pass
1067 pass
1065
1068
1066 return newtext
1069 return newtext
1067
1070
1068
1071
1069 def rst(source):
1072 def rst(source):
1070 return literal('<div class="rst-block">%s</div>' %
1073 return literal('<div class="rst-block">%s</div>' %
1071 MarkupRenderer.rst(source))
1074 MarkupRenderer.rst(source))
1072
1075
1073
1076
1074 def rst_w_mentions(source):
1077 def rst_w_mentions(source):
1075 """
1078 """
1076 Wrapped rst renderer with @mention highlighting
1079 Wrapped rst renderer with @mention highlighting
1077
1080
1078 :param source:
1081 :param source:
1079 """
1082 """
1080 return literal('<div class="rst-block">%s</div>' %
1083 return literal('<div class="rst-block">%s</div>' %
1081 MarkupRenderer.rst_with_mentions(source))
1084 MarkupRenderer.rst_with_mentions(source))
1082
1085
1083
1086
1084 def changeset_status(repo, revision):
1087 def changeset_status(repo, revision):
1085 return ChangesetStatusModel().get_status(repo, revision)
1088 return ChangesetStatusModel().get_status(repo, revision)
1086
1089
1087
1090
1088 def changeset_status_lbl(changeset_status):
1091 def changeset_status_lbl(changeset_status):
1089 return dict(ChangesetStatus.STATUSES).get(changeset_status)
1092 return dict(ChangesetStatus.STATUSES).get(changeset_status)
1090
1093
1091
1094
1092 def get_permission_name(key):
1095 def get_permission_name(key):
1093 return dict(Permission.PERMS).get(key)
1096 return dict(Permission.PERMS).get(key)
General Comments 0
You need to be logged in to leave comments. Login now