##// END OF EJS Templates
Cached readme generation...
marcink -
r1607:e886f91f beta
parent child Browse files
Show More
@@ -1,235 +1,241 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
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 #smtp_auth =
28 #smtp_auth =
29
29
30 [server:main]
30 [server:main]
31 ##nr of threads to spawn
31 ##nr of threads to spawn
32 threadpool_workers = 5
32 threadpool_workers = 5
33
33
34 ##max request before thread respawn
34 ##max request before thread respawn
35 threadpool_max_requests = 6
35 threadpool_max_requests = 6
36
36
37 ##option to use threads of process
37 ##option to use threads of process
38 use_threadpool = true
38 use_threadpool = true
39
39
40 use = egg:Paste#http
40 use = egg:Paste#http
41 host = 0.0.0.0
41 host = 0.0.0.0
42 port = 5000
42 port = 5000
43
43
44 [app:main]
44 [app:main]
45 use = egg:rhodecode
45 use = egg:rhodecode
46 full_stack = true
46 full_stack = true
47 static_files = true
47 static_files = true
48 lang=en
48 lang=en
49 cache_dir = %(here)s/data
49 cache_dir = %(here)s/data
50 index_dir = %(here)s/data/index
50 index_dir = %(here)s/data/index
51 app_instance_uuid = develop
51 app_instance_uuid = develop
52 cut_off_limit = 256000
52 cut_off_limit = 256000
53 force_https = false
53 force_https = false
54 commit_parse_limit = 25
54 commit_parse_limit = 25
55 use_gravatar = true
55 use_gravatar = true
56
56
57 ####################################
57 ####################################
58 ### CELERY CONFIG ####
58 ### CELERY CONFIG ####
59 ####################################
59 ####################################
60 use_celery = false
60 use_celery = false
61 broker.host = localhost
61 broker.host = localhost
62 broker.vhost = rabbitmqhost
62 broker.vhost = rabbitmqhost
63 broker.port = 5672
63 broker.port = 5672
64 broker.user = rabbitmq
64 broker.user = rabbitmq
65 broker.password = qweqwe
65 broker.password = qweqwe
66
66
67 celery.imports = rhodecode.lib.celerylib.tasks
67 celery.imports = rhodecode.lib.celerylib.tasks
68
68
69 celery.result.backend = amqp
69 celery.result.backend = amqp
70 celery.result.dburi = amqp://
70 celery.result.dburi = amqp://
71 celery.result.serialier = json
71 celery.result.serialier = json
72
72
73 #celery.send.task.error.emails = true
73 #celery.send.task.error.emails = true
74 #celery.amqp.task.result.expires = 18000
74 #celery.amqp.task.result.expires = 18000
75
75
76 celeryd.concurrency = 2
76 celeryd.concurrency = 2
77 #celeryd.log.file = celeryd.log
77 #celeryd.log.file = celeryd.log
78 celeryd.log.level = debug
78 celeryd.log.level = debug
79 celeryd.max.tasks.per.child = 1
79 celeryd.max.tasks.per.child = 1
80
80
81 #tasks will never be sent to the queue, but executed locally instead.
81 #tasks will never be sent to the queue, but executed locally instead.
82 celery.always.eager = false
82 celery.always.eager = false
83
83
84 ####################################
84 ####################################
85 ### BEAKER CACHE ####
85 ### BEAKER CACHE ####
86 ####################################
86 ####################################
87 beaker.cache.data_dir=%(here)s/data/cache/data
87 beaker.cache.data_dir=%(here)s/data/cache/data
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
89
89
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
91
91
92 beaker.cache.super_short_term.type=memory
92 beaker.cache.super_short_term.type=memory
93 beaker.cache.super_short_term.expire=10
93 beaker.cache.super_short_term.expire=10
94 beaker.cache.super_short_term.key_length = 256
94
95
95 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.expire=60
97 beaker.cache.short_term.expire=60
98 beaker.cache.short_term.key_length = 256
97
99
98 beaker.cache.long_term.type=memory
100 beaker.cache.long_term.type=memory
99 beaker.cache.long_term.expire=36000
101 beaker.cache.long_term.expire=36000
102 beaker.cache.long_term.key_length = 256
100
103
101 beaker.cache.sql_cache_short.type=memory
104 beaker.cache.sql_cache_short.type=memory
102 beaker.cache.sql_cache_short.expire=10
105 beaker.cache.sql_cache_short.expire=10
106 beaker.cache.sql_cache_short.key_length = 256
103
107
104 beaker.cache.sql_cache_med.type=memory
108 beaker.cache.sql_cache_med.type=memory
105 beaker.cache.sql_cache_med.expire=360
109 beaker.cache.sql_cache_med.expire=360
110 beaker.cache.sql_cache_med.key_length = 256
106
111
107 beaker.cache.sql_cache_long.type=file
112 beaker.cache.sql_cache_long.type=file
108 beaker.cache.sql_cache_long.expire=3600
113 beaker.cache.sql_cache_long.expire=3600
114 beaker.cache.sql_cache_long.key_length = 256
109
115
110 ####################################
116 ####################################
111 ### BEAKER SESSION ####
117 ### BEAKER SESSION ####
112 ####################################
118 ####################################
113 ## Type of storage used for the session, current types are
119 ## Type of storage used for the session, current types are
114 ## dbm, file, memcached, database, and memory.
120 ## dbm, file, memcached, database, and memory.
115 ## The storage uses the Container API
121 ## The storage uses the Container API
116 ##that is also used by the cache system.
122 ##that is also used by the cache system.
117 beaker.session.type = file
123 beaker.session.type = file
118
124
119 beaker.session.key = rhodecode
125 beaker.session.key = rhodecode
120 beaker.session.secret = g654dcno0-9873jhgfreyu
126 beaker.session.secret = g654dcno0-9873jhgfreyu
121 beaker.session.timeout = 36000
127 beaker.session.timeout = 36000
122
128
123 ##auto save the session to not to use .save()
129 ##auto save the session to not to use .save()
124 beaker.session.auto = False
130 beaker.session.auto = False
125
131
126 ##true exire at browser close
132 ##true exire at browser close
127 #beaker.session.cookie_expires = 3600
133 #beaker.session.cookie_expires = 3600
128
134
129
135
130 ################################################################################
136 ################################################################################
131 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
137 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
132 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
138 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
133 ## execute malicious code after an exception is raised. ##
139 ## execute malicious code after an exception is raised. ##
134 ################################################################################
140 ################################################################################
135 #set debug = false
141 #set debug = false
136
142
137 ##################################
143 ##################################
138 ### LOGVIEW CONFIG ###
144 ### LOGVIEW CONFIG ###
139 ##################################
145 ##################################
140 logview.sqlalchemy = #faa
146 logview.sqlalchemy = #faa
141 logview.pylons.templating = #bfb
147 logview.pylons.templating = #bfb
142 logview.pylons.util = #eee
148 logview.pylons.util = #eee
143
149
144 #########################################################
150 #########################################################
145 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
151 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
146 #########################################################
152 #########################################################
147 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
153 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
148 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
154 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
149 sqlalchemy.db1.echo = false
155 sqlalchemy.db1.echo = false
150 sqlalchemy.db1.pool_recycle = 3600
156 sqlalchemy.db1.pool_recycle = 3600
151 sqlalchemy.convert_unicode = true
157 sqlalchemy.convert_unicode = true
152
158
153 ################################
159 ################################
154 ### LOGGING CONFIGURATION ####
160 ### LOGGING CONFIGURATION ####
155 ################################
161 ################################
156 [loggers]
162 [loggers]
157 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
163 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
158
164
159 [handlers]
165 [handlers]
160 keys = console, console_sql
166 keys = console, console_sql
161
167
162 [formatters]
168 [formatters]
163 keys = generic, color_formatter, color_formatter_sql
169 keys = generic, color_formatter, color_formatter_sql
164
170
165 #############
171 #############
166 ## LOGGERS ##
172 ## LOGGERS ##
167 #############
173 #############
168 [logger_root]
174 [logger_root]
169 level = NOTSET
175 level = NOTSET
170 handlers = console
176 handlers = console
171
177
172 [logger_routes]
178 [logger_routes]
173 level = DEBUG
179 level = DEBUG
174 handlers =
180 handlers =
175 qualname = routes.middleware
181 qualname = routes.middleware
176 # "level = DEBUG" logs the route matched and routing variables.
182 # "level = DEBUG" logs the route matched and routing variables.
177 propagate = 1
183 propagate = 1
178
184
179 [logger_beaker]
185 [logger_beaker]
180 level = DEBUG
186 level = DEBUG
181 handlers =
187 handlers =
182 qualname = beaker.container
188 qualname = beaker.container
183 propagate = 1
189 propagate = 1
184
190
185 [logger_templates]
191 [logger_templates]
186 level = INFO
192 level = INFO
187 handlers =
193 handlers =
188 qualname = pylons.templating
194 qualname = pylons.templating
189 propagate = 1
195 propagate = 1
190
196
191 [logger_rhodecode]
197 [logger_rhodecode]
192 level = DEBUG
198 level = DEBUG
193 handlers =
199 handlers =
194 qualname = rhodecode
200 qualname = rhodecode
195 propagate = 1
201 propagate = 1
196
202
197 [logger_sqlalchemy]
203 [logger_sqlalchemy]
198 level = INFO
204 level = INFO
199 handlers = console_sql
205 handlers = console_sql
200 qualname = sqlalchemy.engine
206 qualname = sqlalchemy.engine
201 propagate = 0
207 propagate = 0
202
208
203 ##############
209 ##############
204 ## HANDLERS ##
210 ## HANDLERS ##
205 ##############
211 ##############
206
212
207 [handler_console]
213 [handler_console]
208 class = StreamHandler
214 class = StreamHandler
209 args = (sys.stderr,)
215 args = (sys.stderr,)
210 level = DEBUG
216 level = DEBUG
211 formatter = color_formatter
217 formatter = color_formatter
212
218
213 [handler_console_sql]
219 [handler_console_sql]
214 class = StreamHandler
220 class = StreamHandler
215 args = (sys.stderr,)
221 args = (sys.stderr,)
216 level = DEBUG
222 level = DEBUG
217 formatter = color_formatter_sql
223 formatter = color_formatter_sql
218
224
219 ################
225 ################
220 ## FORMATTERS ##
226 ## FORMATTERS ##
221 ################
227 ################
222
228
223 [formatter_generic]
229 [formatter_generic]
224 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
230 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
225 datefmt = %Y-%m-%d %H:%M:%S
231 datefmt = %Y-%m-%d %H:%M:%S
226
232
227 [formatter_color_formatter]
233 [formatter_color_formatter]
228 class=rhodecode.lib.colored_formatter.ColorFormatter
234 class=rhodecode.lib.colored_formatter.ColorFormatter
229 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
235 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
230 datefmt = %Y-%m-%d %H:%M:%S
236 datefmt = %Y-%m-%d %H:%M:%S
231
237
232 [formatter_color_formatter_sql]
238 [formatter_color_formatter_sql]
233 class=rhodecode.lib.colored_formatter.ColorFormatterSql
239 class=rhodecode.lib.colored_formatter.ColorFormatterSql
234 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
240 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
235 datefmt = %Y-%m-%d %H:%M:%S
241 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,235 +1,241 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
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 #smtp_auth =
28 #smtp_auth =
29
29
30 [server:main]
30 [server:main]
31 ##nr of threads to spawn
31 ##nr of threads to spawn
32 threadpool_workers = 5
32 threadpool_workers = 5
33
33
34 ##max request before thread respawn
34 ##max request before thread respawn
35 threadpool_max_requests = 10
35 threadpool_max_requests = 10
36
36
37 ##option to use threads of process
37 ##option to use threads of process
38 use_threadpool = true
38 use_threadpool = true
39
39
40 use = egg:Paste#http
40 use = egg:Paste#http
41 host = 127.0.0.1
41 host = 127.0.0.1
42 port = 8001
42 port = 8001
43
43
44 [app:main]
44 [app:main]
45 use = egg:rhodecode
45 use = egg:rhodecode
46 full_stack = true
46 full_stack = true
47 static_files = true
47 static_files = true
48 lang=en
48 lang=en
49 cache_dir = %(here)s/data
49 cache_dir = %(here)s/data
50 index_dir = %(here)s/data/index
50 index_dir = %(here)s/data/index
51 app_instance_uuid = prod1234
51 app_instance_uuid = prod1234
52 cut_off_limit = 256000
52 cut_off_limit = 256000
53 force_https = false
53 force_https = false
54 commit_parse_limit = 50
54 commit_parse_limit = 50
55 use_gravatar = true
55 use_gravatar = true
56
56
57 ####################################
57 ####################################
58 ### CELERY CONFIG ####
58 ### CELERY CONFIG ####
59 ####################################
59 ####################################
60 use_celery = false
60 use_celery = false
61 broker.host = localhost
61 broker.host = localhost
62 broker.vhost = rabbitmqhost
62 broker.vhost = rabbitmqhost
63 broker.port = 5672
63 broker.port = 5672
64 broker.user = rabbitmq
64 broker.user = rabbitmq
65 broker.password = qweqwe
65 broker.password = qweqwe
66
66
67 celery.imports = rhodecode.lib.celerylib.tasks
67 celery.imports = rhodecode.lib.celerylib.tasks
68
68
69 celery.result.backend = amqp
69 celery.result.backend = amqp
70 celery.result.dburi = amqp://
70 celery.result.dburi = amqp://
71 celery.result.serialier = json
71 celery.result.serialier = json
72
72
73 #celery.send.task.error.emails = true
73 #celery.send.task.error.emails = true
74 #celery.amqp.task.result.expires = 18000
74 #celery.amqp.task.result.expires = 18000
75
75
76 celeryd.concurrency = 2
76 celeryd.concurrency = 2
77 #celeryd.log.file = celeryd.log
77 #celeryd.log.file = celeryd.log
78 celeryd.log.level = debug
78 celeryd.log.level = debug
79 celeryd.max.tasks.per.child = 1
79 celeryd.max.tasks.per.child = 1
80
80
81 #tasks will never be sent to the queue, but executed locally instead.
81 #tasks will never be sent to the queue, but executed locally instead.
82 celery.always.eager = false
82 celery.always.eager = false
83
83
84 ####################################
84 ####################################
85 ### BEAKER CACHE ####
85 ### BEAKER CACHE ####
86 ####################################
86 ####################################
87 beaker.cache.data_dir=%(here)s/data/cache/data
87 beaker.cache.data_dir=%(here)s/data/cache/data
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
89
89
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
91
91
92 beaker.cache.super_short_term.type=memory
92 beaker.cache.super_short_term.type=memory
93 beaker.cache.super_short_term.expire=10
93 beaker.cache.super_short_term.expire=10
94 beaker.cache.super_short_term.key_length = 256
94
95
95 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.expire=60
97 beaker.cache.short_term.expire=60
98 beaker.cache.short_term.key_length = 256
97
99
98 beaker.cache.long_term.type=memory
100 beaker.cache.long_term.type=memory
99 beaker.cache.long_term.expire=36000
101 beaker.cache.long_term.expire=36000
102 beaker.cache.long_term.key_length = 256
100
103
101 beaker.cache.sql_cache_short.type=memory
104 beaker.cache.sql_cache_short.type=memory
102 beaker.cache.sql_cache_short.expire=10
105 beaker.cache.sql_cache_short.expire=10
106 beaker.cache.sql_cache_short.key_length = 256
103
107
104 beaker.cache.sql_cache_med.type=memory
108 beaker.cache.sql_cache_med.type=memory
105 beaker.cache.sql_cache_med.expire=360
109 beaker.cache.sql_cache_med.expire=360
110 beaker.cache.sql_cache_med.key_length = 256
106
111
107 beaker.cache.sql_cache_long.type=file
112 beaker.cache.sql_cache_long.type=file
108 beaker.cache.sql_cache_long.expire=3600
113 beaker.cache.sql_cache_long.expire=3600
114 beaker.cache.sql_cache_long.key_length = 256
109
115
110 ####################################
116 ####################################
111 ### BEAKER SESSION ####
117 ### BEAKER SESSION ####
112 ####################################
118 ####################################
113 ## Type of storage used for the session, current types are
119 ## Type of storage used for the session, current types are
114 ## dbm, file, memcached, database, and memory.
120 ## dbm, file, memcached, database, and memory.
115 ## The storage uses the Container API
121 ## The storage uses the Container API
116 ##that is also used by the cache system.
122 ##that is also used by the cache system.
117 beaker.session.type = file
123 beaker.session.type = file
118
124
119 beaker.session.key = rhodecode
125 beaker.session.key = rhodecode
120 beaker.session.secret = g654dcno0-9873jhgfreyu
126 beaker.session.secret = g654dcno0-9873jhgfreyu
121 beaker.session.timeout = 36000
127 beaker.session.timeout = 36000
122
128
123 ##auto save the session to not to use .save()
129 ##auto save the session to not to use .save()
124 beaker.session.auto = False
130 beaker.session.auto = False
125
131
126 ##true exire at browser close
132 ##true exire at browser close
127 #beaker.session.cookie_expires = 3600
133 #beaker.session.cookie_expires = 3600
128
134
129
135
130 ################################################################################
136 ################################################################################
131 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
137 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
132 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
138 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
133 ## execute malicious code after an exception is raised. ##
139 ## execute malicious code after an exception is raised. ##
134 ################################################################################
140 ################################################################################
135 set debug = false
141 set debug = false
136
142
137 ##################################
143 ##################################
138 ### LOGVIEW CONFIG ###
144 ### LOGVIEW CONFIG ###
139 ##################################
145 ##################################
140 logview.sqlalchemy = #faa
146 logview.sqlalchemy = #faa
141 logview.pylons.templating = #bfb
147 logview.pylons.templating = #bfb
142 logview.pylons.util = #eee
148 logview.pylons.util = #eee
143
149
144 #########################################################
150 #########################################################
145 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
151 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
146 #########################################################
152 #########################################################
147 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
153 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
148 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
154 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
149 sqlalchemy.db1.echo = false
155 sqlalchemy.db1.echo = false
150 sqlalchemy.db1.pool_recycle = 3600
156 sqlalchemy.db1.pool_recycle = 3600
151 sqlalchemy.convert_unicode = true
157 sqlalchemy.convert_unicode = true
152
158
153 ################################
159 ################################
154 ### LOGGING CONFIGURATION ####
160 ### LOGGING CONFIGURATION ####
155 ################################
161 ################################
156 [loggers]
162 [loggers]
157 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
163 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
158
164
159 [handlers]
165 [handlers]
160 keys = console, console_sql
166 keys = console, console_sql
161
167
162 [formatters]
168 [formatters]
163 keys = generic, color_formatter, color_formatter_sql
169 keys = generic, color_formatter, color_formatter_sql
164
170
165 #############
171 #############
166 ## LOGGERS ##
172 ## LOGGERS ##
167 #############
173 #############
168 [logger_root]
174 [logger_root]
169 level = NOTSET
175 level = NOTSET
170 handlers = console
176 handlers = console
171
177
172 [logger_routes]
178 [logger_routes]
173 level = DEBUG
179 level = DEBUG
174 handlers =
180 handlers =
175 qualname = routes.middleware
181 qualname = routes.middleware
176 # "level = DEBUG" logs the route matched and routing variables.
182 # "level = DEBUG" logs the route matched and routing variables.
177 propagate = 1
183 propagate = 1
178
184
179 [logger_beaker]
185 [logger_beaker]
180 level = DEBUG
186 level = DEBUG
181 handlers =
187 handlers =
182 qualname = beaker.container
188 qualname = beaker.container
183 propagate = 1
189 propagate = 1
184
190
185 [logger_templates]
191 [logger_templates]
186 level = INFO
192 level = INFO
187 handlers =
193 handlers =
188 qualname = pylons.templating
194 qualname = pylons.templating
189 propagate = 1
195 propagate = 1
190
196
191 [logger_rhodecode]
197 [logger_rhodecode]
192 level = DEBUG
198 level = DEBUG
193 handlers =
199 handlers =
194 qualname = rhodecode
200 qualname = rhodecode
195 propagate = 1
201 propagate = 1
196
202
197 [logger_sqlalchemy]
203 [logger_sqlalchemy]
198 level = INFO
204 level = INFO
199 handlers = console_sql
205 handlers = console_sql
200 qualname = sqlalchemy.engine
206 qualname = sqlalchemy.engine
201 propagate = 0
207 propagate = 0
202
208
203 ##############
209 ##############
204 ## HANDLERS ##
210 ## HANDLERS ##
205 ##############
211 ##############
206
212
207 [handler_console]
213 [handler_console]
208 class = StreamHandler
214 class = StreamHandler
209 args = (sys.stderr,)
215 args = (sys.stderr,)
210 level = INFO
216 level = INFO
211 formatter = generic
217 formatter = generic
212
218
213 [handler_console_sql]
219 [handler_console_sql]
214 class = StreamHandler
220 class = StreamHandler
215 args = (sys.stderr,)
221 args = (sys.stderr,)
216 level = WARN
222 level = WARN
217 formatter = generic
223 formatter = generic
218
224
219 ################
225 ################
220 ## FORMATTERS ##
226 ## FORMATTERS ##
221 ################
227 ################
222
228
223 [formatter_generic]
229 [formatter_generic]
224 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
230 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
225 datefmt = %Y-%m-%d %H:%M:%S
231 datefmt = %Y-%m-%d %H:%M:%S
226
232
227 [formatter_color_formatter]
233 [formatter_color_formatter]
228 class=rhodecode.lib.colored_formatter.ColorFormatter
234 class=rhodecode.lib.colored_formatter.ColorFormatter
229 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
235 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
230 datefmt = %Y-%m-%d %H:%M:%S
236 datefmt = %Y-%m-%d %H:%M:%S
231
237
232 [formatter_color_formatter_sql]
238 [formatter_color_formatter_sql]
233 class=rhodecode.lib.colored_formatter.ColorFormatterSql
239 class=rhodecode.lib.colored_formatter.ColorFormatterSql
234 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
240 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
235 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
241 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,244 +1,251 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
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 #smtp_auth =
28 #smtp_auth =
29
29
30 [server:main]
30 [server:main]
31 ##nr of threads to spawn
31 ##nr of threads to spawn
32 threadpool_workers = 5
32 threadpool_workers = 5
33
33
34 ##max request before thread respawn
34 ##max request before thread respawn
35 threadpool_max_requests = 10
35 threadpool_max_requests = 10
36
36
37 ##option to use threads of process
37 ##option to use threads of process
38 use_threadpool = true
38 use_threadpool = true
39
39
40 use = egg:Paste#http
40 use = egg:Paste#http
41 host = 127.0.0.1
41 host = 127.0.0.1
42 port = 5000
42 port = 5000
43
43
44 [app:main]
44 [app:main]
45 use = egg:rhodecode
45 use = egg:rhodecode
46 full_stack = true
46 full_stack = true
47 static_files = true
47 static_files = true
48 lang=en
48 lang=en
49 cache_dir = %(here)s/data
49 cache_dir = %(here)s/data
50 index_dir = %(here)s/data/index
50 index_dir = %(here)s/data/index
51 app_instance_uuid = ${app_instance_uuid}
51 app_instance_uuid = ${app_instance_uuid}
52 cut_off_limit = 256000
52 cut_off_limit = 256000
53 force_https = false
53 force_https = false
54 commit_parse_limit = 50
54 commit_parse_limit = 50
55 use_gravatar = true
55 use_gravatar = true
56
56
57 ####################################
57 ####################################
58 ### CELERY CONFIG ####
58 ### CELERY CONFIG ####
59 ####################################
59 ####################################
60 use_celery = false
60 use_celery = false
61 broker.host = localhost
61 broker.host = localhost
62 broker.vhost = rabbitmqhost
62 broker.vhost = rabbitmqhost
63 broker.port = 5672
63 broker.port = 5672
64 broker.user = rabbitmq
64 broker.user = rabbitmq
65 broker.password = qweqwe
65 broker.password = qweqwe
66
66
67 celery.imports = rhodecode.lib.celerylib.tasks
67 celery.imports = rhodecode.lib.celerylib.tasks
68
68
69 celery.result.backend = amqp
69 celery.result.backend = amqp
70 celery.result.dburi = amqp://
70 celery.result.dburi = amqp://
71 celery.result.serialier = json
71 celery.result.serialier = json
72
72
73 #celery.send.task.error.emails = true
73 #celery.send.task.error.emails = true
74 #celery.amqp.task.result.expires = 18000
74 #celery.amqp.task.result.expires = 18000
75
75
76 celeryd.concurrency = 2
76 celeryd.concurrency = 2
77 #celeryd.log.file = celeryd.log
77 #celeryd.log.file = celeryd.log
78 celeryd.log.level = debug
78 celeryd.log.level = debug
79 celeryd.max.tasks.per.child = 1
79 celeryd.max.tasks.per.child = 1
80
80
81 #tasks will never be sent to the queue, but executed locally instead.
81 #tasks will never be sent to the queue, but executed locally instead.
82 celery.always.eager = false
82 celery.always.eager = false
83
83
84 ####################################
84 ####################################
85 ### BEAKER CACHE ####
85 ### BEAKER CACHE ####
86 ####################################
86 ####################################
87 beaker.cache.data_dir=%(here)s/data/cache/data
87 beaker.cache.data_dir=%(here)s/data/cache/data
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
89
89
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
91
91
92 beaker.cache.super_short_term.type=memory
92 beaker.cache.super_short_term.type=memory
93 beaker.cache.super_short_term.expire=10
93 beaker.cache.super_short_term.expire=10
94 beaker.cache.super_short_term.key_length = 256
94
95
95 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.type=memory
96 beaker.cache.short_term.expire=60
97 beaker.cache.short_term.expire=60
98 beaker.cache.short_term.key_length = 256
97
99
98 beaker.cache.long_term.type=memory
100 beaker.cache.long_term.type=memory
99 beaker.cache.long_term.expire=36000
101 beaker.cache.long_term.expire=36000
102 beaker.cache.long_term.key_length = 256
100
103
101 beaker.cache.sql_cache_short.type=memory
104 beaker.cache.sql_cache_short.type=memory
102 beaker.cache.sql_cache_short.expire=10
105 beaker.cache.sql_cache_short.expire=10
106 beaker.cache.sql_cache_short.key_length = 256
103
107
104 beaker.cache.sql_cache_med.type=memory
108 beaker.cache.sql_cache_med.type=memory
105 beaker.cache.sql_cache_med.expire=360
109 beaker.cache.sql_cache_med.expire=360
110 beaker.cache.sql_cache_med.key_length = 256
106
111
107 beaker.cache.sql_cache_long.type=file
112 beaker.cache.sql_cache_long.type=file
108 beaker.cache.sql_cache_long.expire=3600
113 beaker.cache.sql_cache_long.expire=3600
114 beaker.cache.sql_cache_long.key_length = 256
109
115
110 ####################################
116 ####################################
111 ### BEAKER SESSION ####
117 ### BEAKER SESSION ####
112 ####################################
118 ####################################
113 ## Type of storage used for the session, current types are
119 ## Type of storage used for the session, current types are
114 ## dbm, file, memcached, database, and memory.
120 ## dbm, file, memcached, database, and memory.
115 ## The storage uses the Container API
121 ## The storage uses the Container API
116 ##that is also used by the cache system.
122 ##that is also used by the cache system.
117 beaker.session.type = file
123 beaker.session.type = file
118
124
119 beaker.session.key = rhodecode
125 beaker.session.key = rhodecode
120 beaker.session.secret = ${app_instance_secret}
126 beaker.session.secret = ${app_instance_secret}
121 beaker.session.timeout = 36000
127 beaker.session.timeout = 36000
122
128
123 ##auto save the session to not to use .save()
129 ##auto save the session to not to use .save()
124 beaker.session.auto = False
130 beaker.session.auto = False
125
131
126 ##true exire at browser close
132 ##true exire at browser close
127 #beaker.session.cookie_expires = 3600
133 #beaker.session.cookie_expires = 3600
128
134
129
135
130 ################################################################################
136 ################################################################################
131 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
137 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
132 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
138 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
133 ## execute malicious code after an exception is raised. ##
139 ## execute malicious code after an exception is raised. ##
134 ################################################################################
140 ################################################################################
135 set debug = false
141 set debug = false
136
142
137 ##################################
143 ##################################
138 ### LOGVIEW CONFIG ###
144 ### LOGVIEW CONFIG ###
139 ##################################
145 ##################################
140 logview.sqlalchemy = #faa
146 logview.sqlalchemy = #faa
141 logview.pylons.templating = #bfb
147 logview.pylons.templating = #bfb
142 logview.pylons.util = #eee
148 logview.pylons.util = #eee
143
149
144 #########################################################
150 #########################################################
145 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
151 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
146 #########################################################
152 #########################################################
147
153
148 # SQLITE [default]
154 # SQLITE [default]
149 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
155 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
150
156
151 # POSTGRESQL
157 # POSTGRESQL
152 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
158 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
153
159
154 # MySQL
160 # MySQL
155 # sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
161 # sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
156
162
163 # see sqlalchemy docs for others
157
164
158 sqlalchemy.db1.echo = false
165 sqlalchemy.db1.echo = false
159 sqlalchemy.db1.pool_recycle = 3600
166 sqlalchemy.db1.pool_recycle = 3600
160 sqlalchemy.convert_unicode = true
167 sqlalchemy.convert_unicode = true
161
168
162 ################################
169 ################################
163 ### LOGGING CONFIGURATION ####
170 ### LOGGING CONFIGURATION ####
164 ################################
171 ################################
165 [loggers]
172 [loggers]
166 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
173 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
167
174
168 [handlers]
175 [handlers]
169 keys = console, console_sql
176 keys = console, console_sql
170
177
171 [formatters]
178 [formatters]
172 keys = generic, color_formatter, color_formatter_sql
179 keys = generic, color_formatter, color_formatter_sql
173
180
174 #############
181 #############
175 ## LOGGERS ##
182 ## LOGGERS ##
176 #############
183 #############
177 [logger_root]
184 [logger_root]
178 level = NOTSET
185 level = NOTSET
179 handlers = console
186 handlers = console
180
187
181 [logger_routes]
188 [logger_routes]
182 level = DEBUG
189 level = DEBUG
183 handlers =
190 handlers =
184 qualname = routes.middleware
191 qualname = routes.middleware
185 # "level = DEBUG" logs the route matched and routing variables.
192 # "level = DEBUG" logs the route matched and routing variables.
186 propagate = 1
193 propagate = 1
187
194
188 [logger_beaker]
195 [logger_beaker]
189 level = DEBUG
196 level = DEBUG
190 handlers =
197 handlers =
191 qualname = beaker.container
198 qualname = beaker.container
192 propagate = 1
199 propagate = 1
193
200
194 [logger_templates]
201 [logger_templates]
195 level = INFO
202 level = INFO
196 handlers =
203 handlers =
197 qualname = pylons.templating
204 qualname = pylons.templating
198 propagate = 1
205 propagate = 1
199
206
200 [logger_rhodecode]
207 [logger_rhodecode]
201 level = DEBUG
208 level = DEBUG
202 handlers =
209 handlers =
203 qualname = rhodecode
210 qualname = rhodecode
204 propagate = 1
211 propagate = 1
205
212
206 [logger_sqlalchemy]
213 [logger_sqlalchemy]
207 level = INFO
214 level = INFO
208 handlers = console_sql
215 handlers = console_sql
209 qualname = sqlalchemy.engine
216 qualname = sqlalchemy.engine
210 propagate = 0
217 propagate = 0
211
218
212 ##############
219 ##############
213 ## HANDLERS ##
220 ## HANDLERS ##
214 ##############
221 ##############
215
222
216 [handler_console]
223 [handler_console]
217 class = StreamHandler
224 class = StreamHandler
218 args = (sys.stderr,)
225 args = (sys.stderr,)
219 level = INFO
226 level = INFO
220 formatter = color_formatter
227 formatter = color_formatter
221
228
222 [handler_console_sql]
229 [handler_console_sql]
223 class = StreamHandler
230 class = StreamHandler
224 args = (sys.stderr,)
231 args = (sys.stderr,)
225 level = WARN
232 level = WARN
226 formatter = color_formatter_sql
233 formatter = color_formatter_sql
227
234
228 ################
235 ################
229 ## FORMATTERS ##
236 ## FORMATTERS ##
230 ################
237 ################
231
238
232 [formatter_generic]
239 [formatter_generic]
233 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
240 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
234 datefmt = %Y-%m-%d %H:%M:%S
241 datefmt = %Y-%m-%d %H:%M:%S
235
242
236 [formatter_color_formatter]
243 [formatter_color_formatter]
237 class=rhodecode.lib.colored_formatter.ColorFormatter
244 class=rhodecode.lib.colored_formatter.ColorFormatter
238 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
245 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
239 datefmt = %Y-%m-%d %H:%M:%S
246 datefmt = %Y-%m-%d %H:%M:%S
240
247
241 [formatter_color_formatter_sql]
248 [formatter_color_formatter_sql]
242 class=rhodecode.lib.colored_formatter.ColorFormatterSql
249 class=rhodecode.lib.colored_formatter.ColorFormatterSql
243 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
250 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
244 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
251 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,214 +1,227 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.summary
3 rhodecode.controllers.summary
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Summary controller for Rhodecode
6 Summary controller for Rhodecode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import traceback
26 import traceback
27 import calendar
27 import calendar
28 import logging
28 import logging
29 from time import mktime
29 from time import mktime
30 from datetime import timedelta, date
30 from datetime import timedelta, date
31 from itertools import product
31 from itertools import product
32
32
33 from vcs.exceptions import ChangesetError, EmptyRepositoryError, \
33 from vcs.exceptions import ChangesetError, EmptyRepositoryError, \
34 NodeDoesNotExistError
34 NodeDoesNotExistError
35
35
36 from pylons import tmpl_context as c, request, url
36 from pylons import tmpl_context as c, request, url
37 from pylons.i18n.translation import _
37 from pylons.i18n.translation import _
38
38
39 from rhodecode.model.db import Statistics
39 from beaker.cache import cache_region, region_invalidate
40
41 from rhodecode.model.db import Statistics, CacheInvalidation
40 from rhodecode.lib import ALL_READMES, ALL_EXTS
42 from rhodecode.lib import ALL_READMES, ALL_EXTS
41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
43 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
42 from rhodecode.lib.base import BaseRepoController, render
44 from rhodecode.lib.base import BaseRepoController, render
43 from rhodecode.lib.utils import EmptyChangeset
45 from rhodecode.lib.utils import EmptyChangeset
44 from rhodecode.lib.markup_renderer import MarkupRenderer
46 from rhodecode.lib.markup_renderer import MarkupRenderer
45 from rhodecode.lib.celerylib import run_task
47 from rhodecode.lib.celerylib import run_task
46 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
48 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
47 LANGUAGES_EXTENSIONS_MAP
49 LANGUAGES_EXTENSIONS_MAP
48 from rhodecode.lib.helpers import RepoPage
50 from rhodecode.lib.helpers import RepoPage
49 from rhodecode.lib.compat import json, OrderedDict
51 from rhodecode.lib.compat import json, OrderedDict
50
52
51 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
52
54
53 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
55 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
54 sorted(list(product(ALL_READMES, ALL_EXTS)),
56 sorted(list(product(ALL_READMES, ALL_EXTS)),
55 key=lambda y:y[0][1] + y[1][1])]
57 key=lambda y:y[0][1] + y[1][1])]
56
58
57 class SummaryController(BaseRepoController):
59 class SummaryController(BaseRepoController):
58
60
59 @LoginRequired()
61 @LoginRequired()
60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
62 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
61 'repository.admin')
63 'repository.admin')
62 def __before__(self):
64 def __before__(self):
63 super(SummaryController, self).__before__()
65 super(SummaryController, self).__before__()
64
66
65 def index(self, repo_name):
67 def index(self, repo_name):
66
68
67 e = request.environ
69 e = request.environ
68 c.dbrepo = dbrepo = c.rhodecode_db_repo
70 c.dbrepo = dbrepo = c.rhodecode_db_repo
69
71
70 c.following = self.scm_model.is_following_repo(repo_name,
72 c.following = self.scm_model.is_following_repo(repo_name,
71 self.rhodecode_user.user_id)
73 self.rhodecode_user.user_id)
72
74
73 def url_generator(**kw):
75 def url_generator(**kw):
74 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
76 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
75
77
76 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
78 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
77 items_per_page=10, url=url_generator)
79 items_per_page=10, url=url_generator)
78
80
79 if self.rhodecode_user.username == 'default':
81 if self.rhodecode_user.username == 'default':
80 #for default(anonymous) user we don't need to pass credentials
82 #for default(anonymous) user we don't need to pass credentials
81 username = ''
83 username = ''
82 password = ''
84 password = ''
83 else:
85 else:
84 username = str(self.rhodecode_user.username)
86 username = str(self.rhodecode_user.username)
85 password = '@'
87 password = '@'
86
88
87 if e.get('wsgi.url_scheme') == 'https':
89 if e.get('wsgi.url_scheme') == 'https':
88 split_s = 'https://'
90 split_s = 'https://'
89 else:
91 else:
90 split_s = 'http://'
92 split_s = 'http://'
91
93
92 qualified_uri = [split_s] + [url.current(qualified=True)\
94 qualified_uri = [split_s] + [url.current(qualified=True)\
93 .split(split_s)[-1]]
95 .split(split_s)[-1]]
94 uri = u'%(proto)s%(user)s%(pass)s%(rest)s' \
96 uri = u'%(proto)s%(user)s%(pass)s%(rest)s' \
95 % {'user': username,
97 % {'user': username,
96 'pass': password,
98 'pass': password,
97 'proto': qualified_uri[0],
99 'proto': qualified_uri[0],
98 'rest': qualified_uri[1]}
100 'rest': qualified_uri[1]}
99 c.clone_repo_url = uri
101 c.clone_repo_url = uri
100 c.repo_tags = OrderedDict()
102 c.repo_tags = OrderedDict()
101 for name, hash in c.rhodecode_repo.tags.items()[:10]:
103 for name, hash in c.rhodecode_repo.tags.items()[:10]:
102 try:
104 try:
103 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
105 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
104 except ChangesetError:
106 except ChangesetError:
105 c.repo_tags[name] = EmptyChangeset(hash)
107 c.repo_tags[name] = EmptyChangeset(hash)
106
108
107 c.repo_branches = OrderedDict()
109 c.repo_branches = OrderedDict()
108 for name, hash in c.rhodecode_repo.branches.items()[:10]:
110 for name, hash in c.rhodecode_repo.branches.items()[:10]:
109 try:
111 try:
110 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
112 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
111 except ChangesetError:
113 except ChangesetError:
112 c.repo_branches[name] = EmptyChangeset(hash)
114 c.repo_branches[name] = EmptyChangeset(hash)
113
115
114 td = date.today() + timedelta(days=1)
116 td = date.today() + timedelta(days=1)
115 td_1m = td - timedelta(days=calendar.mdays[td.month])
117 td_1m = td - timedelta(days=calendar.mdays[td.month])
116 td_1y = td - timedelta(days=365)
118 td_1y = td - timedelta(days=365)
117
119
118 ts_min_m = mktime(td_1m.timetuple())
120 ts_min_m = mktime(td_1m.timetuple())
119 ts_min_y = mktime(td_1y.timetuple())
121 ts_min_y = mktime(td_1y.timetuple())
120 ts_max_y = mktime(td.timetuple())
122 ts_max_y = mktime(td.timetuple())
121
123
122 if dbrepo.enable_statistics:
124 if dbrepo.enable_statistics:
123 c.no_data_msg = _('No data loaded yet')
125 c.no_data_msg = _('No data loaded yet')
124 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
126 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
125 else:
127 else:
126 c.no_data_msg = _('Statistics are disabled for this repository')
128 c.no_data_msg = _('Statistics are disabled for this repository')
127 c.ts_min = ts_min_m
129 c.ts_min = ts_min_m
128 c.ts_max = ts_max_y
130 c.ts_max = ts_max_y
129
131
130 stats = self.sa.query(Statistics)\
132 stats = self.sa.query(Statistics)\
131 .filter(Statistics.repository == dbrepo)\
133 .filter(Statistics.repository == dbrepo)\
132 .scalar()
134 .scalar()
133
135
134 c.stats_percentage = 0
136 c.stats_percentage = 0
135
137
136 if stats and stats.languages:
138 if stats and stats.languages:
137 c.no_data = False is dbrepo.enable_statistics
139 c.no_data = False is dbrepo.enable_statistics
138 lang_stats_d = json.loads(stats.languages)
140 lang_stats_d = json.loads(stats.languages)
139 c.commit_data = stats.commit_activity
141 c.commit_data = stats.commit_activity
140 c.overview_data = stats.commit_activity_combined
142 c.overview_data = stats.commit_activity_combined
141
143
142 lang_stats = ((x, {"count": y,
144 lang_stats = ((x, {"count": y,
143 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
145 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
144 for x, y in lang_stats_d.items())
146 for x, y in lang_stats_d.items())
145
147
146 c.trending_languages = json.dumps(OrderedDict(
148 c.trending_languages = json.dumps(OrderedDict(
147 sorted(lang_stats, reverse=True,
149 sorted(lang_stats, reverse=True,
148 key=lambda k: k[1])[:10]
150 key=lambda k: k[1])[:10]
149 )
151 )
150 )
152 )
151 last_rev = stats.stat_on_revision
153 last_rev = stats.stat_on_revision
152 c.repo_last_rev = c.rhodecode_repo.count() - 1 \
154 c.repo_last_rev = c.rhodecode_repo.count() - 1 \
153 if c.rhodecode_repo.revisions else 0
155 if c.rhodecode_repo.revisions else 0
154 if last_rev == 0 or c.repo_last_rev == 0:
156 if last_rev == 0 or c.repo_last_rev == 0:
155 pass
157 pass
156 else:
158 else:
157 c.stats_percentage = '%.2f' % ((float((last_rev)) /
159 c.stats_percentage = '%.2f' % ((float((last_rev)) /
158 c.repo_last_rev) * 100)
160 c.repo_last_rev) * 100)
159 else:
161 else:
160 c.commit_data = json.dumps({})
162 c.commit_data = json.dumps({})
161 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
163 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
162 c.trending_languages = json.dumps({})
164 c.trending_languages = json.dumps({})
163 c.no_data = True
165 c.no_data = True
164
166
165 c.enable_downloads = dbrepo.enable_downloads
167 c.enable_downloads = dbrepo.enable_downloads
166 if c.enable_downloads:
168 if c.enable_downloads:
167 c.download_options = self._get_download_links(c.rhodecode_repo)
169 c.download_options = self._get_download_links(c.rhodecode_repo)
168
170
169 c.readme_data,c.readme_file = self.__get_readme_data()
171 c.readme_data, c.readme_file = self.__get_readme_data(c.rhodecode_repo)
170 return render('summary/summary.html')
172 return render('summary/summary.html')
171
173
172 def __get_readme_data(self):
174 def __get_readme_data(self, repo):
173 readme_data = None
174 readme_file = None
175
176 try:
177 cs = c.rhodecode_repo.get_changeset('tip')
178 renderer = MarkupRenderer()
179 for f in README_FILES:
180 try:
181 readme = cs.get_node(f)
182 readme_file = f
183 readme_data = renderer.render(readme.content, f)
184 break
185 except NodeDoesNotExistError:
186 continue
187 except ChangesetError:
188 pass
189 except EmptyRepositoryError:
190 pass
191 except Exception:
192 log.error(traceback.format_exc())
193
175
194 return readme_data, readme_file
176 @cache_region('long_term')
177 def _get_readme_from_cache(key):
178 readme_data = None
179 readme_file = None
180 log.debug('Fetching readme file')
181 try:
182 cs = repo.get_changeset('tip')
183 renderer = MarkupRenderer()
184 for f in README_FILES:
185 try:
186 readme = cs.get_node(f)
187 readme_file = f
188 readme_data = renderer.render(readme.content, f)
189 log.debug('Found readme %s' % readme_file)
190 break
191 except NodeDoesNotExistError:
192 continue
193 except ChangesetError:
194 pass
195 except EmptyRepositoryError:
196 pass
197 except Exception:
198 log.error(traceback.format_exc())
199
200 return readme_data, readme_file
201
202 key = repo.name + '_README'
203 inv = CacheInvalidation.invalidate(key)
204 if inv is not None:
205 region_invalidate(_get_readme_from_cache, None, key)
206 CacheInvalidation.set_valid(inv.cache_key)
207 return _get_readme_from_cache(key)
195
208
196 def _get_download_links(self, repo):
209 def _get_download_links(self, repo):
197
210
198 download_l = []
211 download_l = []
199
212
200 branches_group = ([], _("Branches"))
213 branches_group = ([], _("Branches"))
201 tags_group = ([], _("Tags"))
214 tags_group = ([], _("Tags"))
202
215
203 for name, chs in c.rhodecode_repo.branches.items():
216 for name, chs in c.rhodecode_repo.branches.items():
204 #chs = chs.split(':')[-1]
217 #chs = chs.split(':')[-1]
205 branches_group[0].append((chs, name),)
218 branches_group[0].append((chs, name),)
206 download_l.append(branches_group)
219 download_l.append(branches_group)
207
220
208 for name, chs in c.rhodecode_repo.tags.items():
221 for name, chs in c.rhodecode_repo.tags.items():
209 #chs = chs.split(':')[-1]
222 #chs = chs.split(':')[-1]
210 tags_group[0].append((chs, name),)
223 tags_group[0].append((chs, name),)
211 download_l.append(tags_group)
224 download_l.append(tags_group)
212
225
213 return download_l
226 return download_l
214
227
@@ -1,1069 +1,1098 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.db
3 rhodecode.model.db
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 Database Models for RhodeCode
6 Database Models for RhodeCode
7
7
8 :created_on: Apr 08, 2010
8 :created_on: Apr 08, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import datetime
28 import datetime
29 import traceback
29 import traceback
30 from datetime import date
30 from datetime import date
31
31
32 from sqlalchemy import *
32 from sqlalchemy import *
33 from sqlalchemy.ext.hybrid import hybrid_property
33 from sqlalchemy.ext.hybrid import hybrid_property
34 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
34 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
35 from beaker.cache import cache_region, region_invalidate
35 from beaker.cache import cache_region, region_invalidate
36
36
37 from vcs import get_backend
37 from vcs import get_backend
38 from vcs.utils.helpers import get_scm
38 from vcs.utils.helpers import get_scm
39 from vcs.exceptions import VCSError
39 from vcs.exceptions import VCSError
40 from vcs.utils.lazy import LazyProperty
40 from vcs.utils.lazy import LazyProperty
41
41
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
43 generate_api_key, safe_unicode
43 generate_api_key, safe_unicode
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
45 from rhodecode.lib.compat import json
45 from rhodecode.lib.compat import json
46
46
47 from rhodecode.model.meta import Base, Session
47 from rhodecode.model.meta import Base, Session
48 from rhodecode.model.caching_query import FromCache
48 from rhodecode.model.caching_query import FromCache
49
49
50
50
51 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
52
52
53 #==============================================================================
53 #==============================================================================
54 # BASE CLASSES
54 # BASE CLASSES
55 #==============================================================================
55 #==============================================================================
56
56
57 class ModelSerializer(json.JSONEncoder):
57 class ModelSerializer(json.JSONEncoder):
58 """
58 """
59 Simple Serializer for JSON,
59 Simple Serializer for JSON,
60
60
61 usage::
61 usage::
62
62
63 to make object customized for serialization implement a __json__
63 to make object customized for serialization implement a __json__
64 method that will return a dict for serialization into json
64 method that will return a dict for serialization into json
65
65
66 example::
66 example::
67
67
68 class Task(object):
68 class Task(object):
69
69
70 def __init__(self, name, value):
70 def __init__(self, name, value):
71 self.name = name
71 self.name = name
72 self.value = value
72 self.value = value
73
73
74 def __json__(self):
74 def __json__(self):
75 return dict(name=self.name,
75 return dict(name=self.name,
76 value=self.value)
76 value=self.value)
77
77
78 """
78 """
79
79
80 def default(self, obj):
80 def default(self, obj):
81
81
82 if hasattr(obj, '__json__'):
82 if hasattr(obj, '__json__'):
83 return obj.__json__()
83 return obj.__json__()
84 else:
84 else:
85 return json.JSONEncoder.default(self, obj)
85 return json.JSONEncoder.default(self, obj)
86
86
87 class BaseModel(object):
87 class BaseModel(object):
88 """Base Model for all classess
88 """Base Model for all classess
89
89
90 """
90 """
91
91
92 @classmethod
92 @classmethod
93 def _get_keys(cls):
93 def _get_keys(cls):
94 """return column names for this model """
94 """return column names for this model """
95 return class_mapper(cls).c.keys()
95 return class_mapper(cls).c.keys()
96
96
97 def get_dict(self):
97 def get_dict(self):
98 """return dict with keys and values corresponding
98 """return dict with keys and values corresponding
99 to this model data """
99 to this model data """
100
100
101 d = {}
101 d = {}
102 for k in self._get_keys():
102 for k in self._get_keys():
103 d[k] = getattr(self, k)
103 d[k] = getattr(self, k)
104 return d
104 return d
105
105
106 def get_appstruct(self):
106 def get_appstruct(self):
107 """return list with keys and values tupples corresponding
107 """return list with keys and values tupples corresponding
108 to this model data """
108 to this model data """
109
109
110 l = []
110 l = []
111 for k in self._get_keys():
111 for k in self._get_keys():
112 l.append((k, getattr(self, k),))
112 l.append((k, getattr(self, k),))
113 return l
113 return l
114
114
115 def populate_obj(self, populate_dict):
115 def populate_obj(self, populate_dict):
116 """populate model with data from given populate_dict"""
116 """populate model with data from given populate_dict"""
117
117
118 for k in self._get_keys():
118 for k in self._get_keys():
119 if k in populate_dict:
119 if k in populate_dict:
120 setattr(self, k, populate_dict[k])
120 setattr(self, k, populate_dict[k])
121
121
122 @classmethod
122 @classmethod
123 def query(cls):
123 def query(cls):
124 return Session.query(cls)
124 return Session.query(cls)
125
125
126 @classmethod
126 @classmethod
127 def get(cls, id_):
127 def get(cls, id_):
128 if id_:
128 if id_:
129 return cls.query().get(id_)
129 return cls.query().get(id_)
130
130
131 @classmethod
131 @classmethod
132 def getAll(cls):
132 def getAll(cls):
133 return cls.query().all()
133 return cls.query().all()
134
134
135 @classmethod
135 @classmethod
136 def delete(cls, id_):
136 def delete(cls, id_):
137 obj = cls.query().get(id_)
137 obj = cls.query().get(id_)
138 Session.delete(obj)
138 Session.delete(obj)
139 Session.commit()
139 Session.commit()
140
140
141
141
142 class RhodeCodeSettings(Base, BaseModel):
142 class RhodeCodeSettings(Base, BaseModel):
143 __tablename__ = 'rhodecode_settings'
143 __tablename__ = 'rhodecode_settings'
144 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
144 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
145 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
145 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
146 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
146 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
147 _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
147 _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
148
148
149 def __init__(self, k='', v=''):
149 def __init__(self, k='', v=''):
150 self.app_settings_name = k
150 self.app_settings_name = k
151 self.app_settings_value = v
151 self.app_settings_value = v
152
152
153
153
154 @validates('_app_settings_value')
154 @validates('_app_settings_value')
155 def validate_settings_value(self, key, val):
155 def validate_settings_value(self, key, val):
156 assert type(val) == unicode
156 assert type(val) == unicode
157 return val
157 return val
158
158
159 @hybrid_property
159 @hybrid_property
160 def app_settings_value(self):
160 def app_settings_value(self):
161 v = self._app_settings_value
161 v = self._app_settings_value
162 if v == 'ldap_active':
162 if v == 'ldap_active':
163 v = str2bool(v)
163 v = str2bool(v)
164 return v
164 return v
165
165
166 @app_settings_value.setter
166 @app_settings_value.setter
167 def app_settings_value(self, val):
167 def app_settings_value(self, val):
168 """
168 """
169 Setter that will always make sure we use unicode in app_settings_value
169 Setter that will always make sure we use unicode in app_settings_value
170
170
171 :param val:
171 :param val:
172 """
172 """
173 self._app_settings_value = safe_unicode(val)
173 self._app_settings_value = safe_unicode(val)
174
174
175 def __repr__(self):
175 def __repr__(self):
176 return "<%s('%s:%s')>" % (self.__class__.__name__,
176 return "<%s('%s:%s')>" % (self.__class__.__name__,
177 self.app_settings_name, self.app_settings_value)
177 self.app_settings_name, self.app_settings_value)
178
178
179
179
180 @classmethod
180 @classmethod
181 def get_by_name(cls, ldap_key):
181 def get_by_name(cls, ldap_key):
182 return cls.query()\
182 return cls.query()\
183 .filter(cls.app_settings_name == ldap_key).scalar()
183 .filter(cls.app_settings_name == ldap_key).scalar()
184
184
185 @classmethod
185 @classmethod
186 def get_app_settings(cls, cache=False):
186 def get_app_settings(cls, cache=False):
187
187
188 ret = cls.query()
188 ret = cls.query()
189
189
190 if cache:
190 if cache:
191 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
191 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
192
192
193 if not ret:
193 if not ret:
194 raise Exception('Could not get application settings !')
194 raise Exception('Could not get application settings !')
195 settings = {}
195 settings = {}
196 for each in ret:
196 for each in ret:
197 settings['rhodecode_' + each.app_settings_name] = \
197 settings['rhodecode_' + each.app_settings_name] = \
198 each.app_settings_value
198 each.app_settings_value
199
199
200 return settings
200 return settings
201
201
202 @classmethod
202 @classmethod
203 def get_ldap_settings(cls, cache=False):
203 def get_ldap_settings(cls, cache=False):
204 ret = cls.query()\
204 ret = cls.query()\
205 .filter(cls.app_settings_name.startswith('ldap_')).all()
205 .filter(cls.app_settings_name.startswith('ldap_')).all()
206 fd = {}
206 fd = {}
207 for row in ret:
207 for row in ret:
208 fd.update({row.app_settings_name:row.app_settings_value})
208 fd.update({row.app_settings_name:row.app_settings_value})
209
209
210 return fd
210 return fd
211
211
212
212
213 class RhodeCodeUi(Base, BaseModel):
213 class RhodeCodeUi(Base, BaseModel):
214 __tablename__ = 'rhodecode_ui'
214 __tablename__ = 'rhodecode_ui'
215 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
215 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
216
216
217 HOOK_UPDATE = 'changegroup.update'
217 HOOK_UPDATE = 'changegroup.update'
218 HOOK_REPO_SIZE = 'changegroup.repo_size'
218 HOOK_REPO_SIZE = 'changegroup.repo_size'
219 HOOK_PUSH = 'pretxnchangegroup.push_logger'
219 HOOK_PUSH = 'pretxnchangegroup.push_logger'
220 HOOK_PULL = 'preoutgoing.pull_logger'
220 HOOK_PULL = 'preoutgoing.pull_logger'
221
221
222 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
222 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
223 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
223 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
224 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
224 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
225 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
225 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
226 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
226 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
227
227
228
228
229 @classmethod
229 @classmethod
230 def get_by_key(cls, key):
230 def get_by_key(cls, key):
231 return cls.query().filter(cls.ui_key == key)
231 return cls.query().filter(cls.ui_key == key)
232
232
233
233
234 @classmethod
234 @classmethod
235 def get_builtin_hooks(cls):
235 def get_builtin_hooks(cls):
236 q = cls.query()
236 q = cls.query()
237 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
237 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
238 cls.HOOK_REPO_SIZE,
238 cls.HOOK_REPO_SIZE,
239 cls.HOOK_PUSH, cls.HOOK_PULL]))
239 cls.HOOK_PUSH, cls.HOOK_PULL]))
240 return q.all()
240 return q.all()
241
241
242 @classmethod
242 @classmethod
243 def get_custom_hooks(cls):
243 def get_custom_hooks(cls):
244 q = cls.query()
244 q = cls.query()
245 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
245 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
246 cls.HOOK_REPO_SIZE,
246 cls.HOOK_REPO_SIZE,
247 cls.HOOK_PUSH, cls.HOOK_PULL]))
247 cls.HOOK_PUSH, cls.HOOK_PULL]))
248 q = q.filter(cls.ui_section == 'hooks')
248 q = q.filter(cls.ui_section == 'hooks')
249 return q.all()
249 return q.all()
250
250
251 @classmethod
251 @classmethod
252 def create_or_update_hook(cls, key, val):
252 def create_or_update_hook(cls, key, val):
253 new_ui = cls.get_by_key(key).scalar() or cls()
253 new_ui = cls.get_by_key(key).scalar() or cls()
254 new_ui.ui_section = 'hooks'
254 new_ui.ui_section = 'hooks'
255 new_ui.ui_active = True
255 new_ui.ui_active = True
256 new_ui.ui_key = key
256 new_ui.ui_key = key
257 new_ui.ui_value = val
257 new_ui.ui_value = val
258
258
259 Session.add(new_ui)
259 Session.add(new_ui)
260 Session.commit()
260 Session.commit()
261
261
262
262
263 class User(Base, BaseModel):
263 class User(Base, BaseModel):
264 __tablename__ = 'users'
264 __tablename__ = 'users'
265 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
265 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
266 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
266 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
267 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
267 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
268 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
268 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
269 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
269 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
270 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
270 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
271 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
271 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
272 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
272 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
273 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
273 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
274 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
274 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
275 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
275 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
276 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
276 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
277
277
278 user_log = relationship('UserLog', cascade='all')
278 user_log = relationship('UserLog', cascade='all')
279 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
279 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
280
280
281 repositories = relationship('Repository')
281 repositories = relationship('Repository')
282 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
282 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
283 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
283 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
284
284
285 group_member = relationship('UsersGroupMember', cascade='all')
285 group_member = relationship('UsersGroupMember', cascade='all')
286
286
287 @property
287 @property
288 def full_contact(self):
288 def full_contact(self):
289 return '%s %s <%s>' % (self.name, self.lastname, self.email)
289 return '%s %s <%s>' % (self.name, self.lastname, self.email)
290
290
291 @property
291 @property
292 def short_contact(self):
292 def short_contact(self):
293 return '%s %s' % (self.name, self.lastname)
293 return '%s %s' % (self.name, self.lastname)
294
294
295 @property
295 @property
296 def is_admin(self):
296 def is_admin(self):
297 return self.admin
297 return self.admin
298
298
299 def __repr__(self):
299 def __repr__(self):
300 try:
300 try:
301 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
301 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
302 self.user_id, self.username)
302 self.user_id, self.username)
303 except:
303 except:
304 return self.__class__.__name__
304 return self.__class__.__name__
305
305
306 @classmethod
306 @classmethod
307 def get_by_username(cls, username, case_insensitive=False):
307 def get_by_username(cls, username, case_insensitive=False):
308 if case_insensitive:
308 if case_insensitive:
309 return Session.query(cls).filter(cls.username.ilike(username)).scalar()
309 return Session.query(cls).filter(cls.username.ilike(username)).scalar()
310 else:
310 else:
311 return Session.query(cls).filter(cls.username == username).scalar()
311 return Session.query(cls).filter(cls.username == username).scalar()
312
312
313 @classmethod
313 @classmethod
314 def get_by_api_key(cls, api_key):
314 def get_by_api_key(cls, api_key):
315 return cls.query().filter(cls.api_key == api_key).one()
315 return cls.query().filter(cls.api_key == api_key).one()
316
316
317 def update_lastlogin(self):
317 def update_lastlogin(self):
318 """Update user lastlogin"""
318 """Update user lastlogin"""
319
319
320 self.last_login = datetime.datetime.now()
320 self.last_login = datetime.datetime.now()
321 Session.add(self)
321 Session.add(self)
322 Session.commit()
322 Session.commit()
323 log.debug('updated user %s lastlogin', self.username)
323 log.debug('updated user %s lastlogin', self.username)
324
324
325 @classmethod
325 @classmethod
326 def create(cls, form_data):
326 def create(cls, form_data):
327 from rhodecode.lib.auth import get_crypt_password
327 from rhodecode.lib.auth import get_crypt_password
328
328
329 try:
329 try:
330 new_user = cls()
330 new_user = cls()
331 for k, v in form_data.items():
331 for k, v in form_data.items():
332 if k == 'password':
332 if k == 'password':
333 v = get_crypt_password(v)
333 v = get_crypt_password(v)
334 setattr(new_user, k, v)
334 setattr(new_user, k, v)
335
335
336 new_user.api_key = generate_api_key(form_data['username'])
336 new_user.api_key = generate_api_key(form_data['username'])
337 Session.add(new_user)
337 Session.add(new_user)
338 Session.commit()
338 Session.commit()
339 return new_user
339 return new_user
340 except:
340 except:
341 log.error(traceback.format_exc())
341 log.error(traceback.format_exc())
342 Session.rollback()
342 Session.rollback()
343 raise
343 raise
344
344
345 class UserLog(Base, BaseModel):
345 class UserLog(Base, BaseModel):
346 __tablename__ = 'user_logs'
346 __tablename__ = 'user_logs'
347 __table_args__ = {'extend_existing':True}
347 __table_args__ = {'extend_existing':True}
348 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
348 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
349 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
349 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
350 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
350 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
351 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
351 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
352 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
352 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
353 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
353 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
354 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
354 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
355
355
356 @property
356 @property
357 def action_as_day(self):
357 def action_as_day(self):
358 return date(*self.action_date.timetuple()[:3])
358 return date(*self.action_date.timetuple()[:3])
359
359
360 user = relationship('User')
360 user = relationship('User')
361 repository = relationship('Repository')
361 repository = relationship('Repository')
362
362
363
363
364 class UsersGroup(Base, BaseModel):
364 class UsersGroup(Base, BaseModel):
365 __tablename__ = 'users_groups'
365 __tablename__ = 'users_groups'
366 __table_args__ = {'extend_existing':True}
366 __table_args__ = {'extend_existing':True}
367
367
368 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
368 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
369 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
369 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
370 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
370 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
371
371
372 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
372 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
373
373
374 def __repr__(self):
374 def __repr__(self):
375 return '<userGroup(%s)>' % (self.users_group_name)
375 return '<userGroup(%s)>' % (self.users_group_name)
376
376
377 @classmethod
377 @classmethod
378 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
378 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
379 if case_insensitive:
379 if case_insensitive:
380 gr = cls.query()\
380 gr = cls.query()\
381 .filter(cls.users_group_name.ilike(group_name))
381 .filter(cls.users_group_name.ilike(group_name))
382 else:
382 else:
383 gr = cls.query()\
383 gr = cls.query()\
384 .filter(cls.users_group_name == group_name)
384 .filter(cls.users_group_name == group_name)
385 if cache:
385 if cache:
386 gr = gr.options(FromCache("sql_cache_short",
386 gr = gr.options(FromCache("sql_cache_short",
387 "get_user_%s" % group_name))
387 "get_user_%s" % group_name))
388 return gr.scalar()
388 return gr.scalar()
389
389
390
390
391 @classmethod
391 @classmethod
392 def get(cls, users_group_id, cache=False):
392 def get(cls, users_group_id, cache=False):
393 users_group = cls.query()
393 users_group = cls.query()
394 if cache:
394 if cache:
395 users_group = users_group.options(FromCache("sql_cache_short",
395 users_group = users_group.options(FromCache("sql_cache_short",
396 "get_users_group_%s" % users_group_id))
396 "get_users_group_%s" % users_group_id))
397 return users_group.get(users_group_id)
397 return users_group.get(users_group_id)
398
398
399 @classmethod
399 @classmethod
400 def create(cls, form_data):
400 def create(cls, form_data):
401 try:
401 try:
402 new_users_group = cls()
402 new_users_group = cls()
403 for k, v in form_data.items():
403 for k, v in form_data.items():
404 setattr(new_users_group, k, v)
404 setattr(new_users_group, k, v)
405
405
406 Session.add(new_users_group)
406 Session.add(new_users_group)
407 Session.commit()
407 Session.commit()
408 return new_users_group
408 return new_users_group
409 except:
409 except:
410 log.error(traceback.format_exc())
410 log.error(traceback.format_exc())
411 Session.rollback()
411 Session.rollback()
412 raise
412 raise
413
413
414 @classmethod
414 @classmethod
415 def update(cls, users_group_id, form_data):
415 def update(cls, users_group_id, form_data):
416
416
417 try:
417 try:
418 users_group = cls.get(users_group_id, cache=False)
418 users_group = cls.get(users_group_id, cache=False)
419
419
420 for k, v in form_data.items():
420 for k, v in form_data.items():
421 if k == 'users_group_members':
421 if k == 'users_group_members':
422 users_group.members = []
422 users_group.members = []
423 Session.flush()
423 Session.flush()
424 members_list = []
424 members_list = []
425 if v:
425 if v:
426 v = [v] if isinstance(v, basestring) else v
426 v = [v] if isinstance(v, basestring) else v
427 for u_id in set(v):
427 for u_id in set(v):
428 member = UsersGroupMember(users_group_id, u_id)
428 member = UsersGroupMember(users_group_id, u_id)
429 members_list.append(member)
429 members_list.append(member)
430 setattr(users_group, 'members', members_list)
430 setattr(users_group, 'members', members_list)
431 setattr(users_group, k, v)
431 setattr(users_group, k, v)
432
432
433 Session.add(users_group)
433 Session.add(users_group)
434 Session.commit()
434 Session.commit()
435 except:
435 except:
436 log.error(traceback.format_exc())
436 log.error(traceback.format_exc())
437 Session.rollback()
437 Session.rollback()
438 raise
438 raise
439
439
440 @classmethod
440 @classmethod
441 def delete(cls, users_group_id):
441 def delete(cls, users_group_id):
442 try:
442 try:
443
443
444 # check if this group is not assigned to repo
444 # check if this group is not assigned to repo
445 assigned_groups = UsersGroupRepoToPerm.query()\
445 assigned_groups = UsersGroupRepoToPerm.query()\
446 .filter(UsersGroupRepoToPerm.users_group_id ==
446 .filter(UsersGroupRepoToPerm.users_group_id ==
447 users_group_id).all()
447 users_group_id).all()
448
448
449 if assigned_groups:
449 if assigned_groups:
450 raise UsersGroupsAssignedException('Group assigned to %s' %
450 raise UsersGroupsAssignedException('Group assigned to %s' %
451 assigned_groups)
451 assigned_groups)
452
452
453 users_group = cls.get(users_group_id, cache=False)
453 users_group = cls.get(users_group_id, cache=False)
454 Session.delete(users_group)
454 Session.delete(users_group)
455 Session.commit()
455 Session.commit()
456 except:
456 except:
457 log.error(traceback.format_exc())
457 log.error(traceback.format_exc())
458 Session.rollback()
458 Session.rollback()
459 raise
459 raise
460
460
461 class UsersGroupMember(Base, BaseModel):
461 class UsersGroupMember(Base, BaseModel):
462 __tablename__ = 'users_groups_members'
462 __tablename__ = 'users_groups_members'
463 __table_args__ = {'extend_existing':True}
463 __table_args__ = {'extend_existing':True}
464
464
465 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
465 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
466 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
466 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
468
468
469 user = relationship('User', lazy='joined')
469 user = relationship('User', lazy='joined')
470 users_group = relationship('UsersGroup')
470 users_group = relationship('UsersGroup')
471
471
472 def __init__(self, gr_id='', u_id=''):
472 def __init__(self, gr_id='', u_id=''):
473 self.users_group_id = gr_id
473 self.users_group_id = gr_id
474 self.user_id = u_id
474 self.user_id = u_id
475
475
476 @staticmethod
476 @staticmethod
477 def add_user_to_group(group, user):
477 def add_user_to_group(group, user):
478 ugm = UsersGroupMember()
478 ugm = UsersGroupMember()
479 ugm.users_group = group
479 ugm.users_group = group
480 ugm.user = user
480 ugm.user = user
481 Session.add(ugm)
481 Session.add(ugm)
482 Session.commit()
482 Session.commit()
483 return ugm
483 return ugm
484
484
485 class Repository(Base, BaseModel):
485 class Repository(Base, BaseModel):
486 __tablename__ = 'repositories'
486 __tablename__ = 'repositories'
487 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
487 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
488
488
489 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
489 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
490 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
490 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
491 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
491 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
492 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
492 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
493 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
493 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
494 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
494 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
495 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
495 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
496 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
496 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
497 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
497 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
498 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
498 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
499
499
500 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
500 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
501 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
501 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
502
502
503
503
504 user = relationship('User')
504 user = relationship('User')
505 fork = relationship('Repository', remote_side=repo_id)
505 fork = relationship('Repository', remote_side=repo_id)
506 group = relationship('Group')
506 group = relationship('Group')
507 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
507 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
508 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
508 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
509 stats = relationship('Statistics', cascade='all', uselist=False)
509 stats = relationship('Statistics', cascade='all', uselist=False)
510
510
511 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
511 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
512
512
513 logs = relationship('UserLog', cascade='all')
513 logs = relationship('UserLog', cascade='all')
514
514
515 def __repr__(self):
515 def __repr__(self):
516 return "<%s('%s:%s')>" % (self.__class__.__name__,
516 return "<%s('%s:%s')>" % (self.__class__.__name__,
517 self.repo_id, self.repo_name)
517 self.repo_id, self.repo_name)
518
518
519 @classmethod
519 @classmethod
520 def url_sep(cls):
520 def url_sep(cls):
521 return '/'
521 return '/'
522
522
523 @classmethod
523 @classmethod
524 def get_by_repo_name(cls, repo_name):
524 def get_by_repo_name(cls, repo_name):
525 q = Session.query(cls).filter(cls.repo_name == repo_name)
525 q = Session.query(cls).filter(cls.repo_name == repo_name)
526 q = q.options(joinedload(Repository.fork))\
526 q = q.options(joinedload(Repository.fork))\
527 .options(joinedload(Repository.user))\
527 .options(joinedload(Repository.user))\
528 .options(joinedload(Repository.group))
528 .options(joinedload(Repository.group))
529 return q.one()
529 return q.one()
530
530
531 @classmethod
531 @classmethod
532 def get_repo_forks(cls, repo_id):
532 def get_repo_forks(cls, repo_id):
533 return cls.query().filter(Repository.fork_id == repo_id)
533 return cls.query().filter(Repository.fork_id == repo_id)
534
534
535 @classmethod
535 @classmethod
536 def base_path(cls):
536 def base_path(cls):
537 """
537 """
538 Returns base path when all repos are stored
538 Returns base path when all repos are stored
539
539
540 :param cls:
540 :param cls:
541 """
541 """
542 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
542 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
543 cls.url_sep())
543 cls.url_sep())
544 q.options(FromCache("sql_cache_short", "repository_repo_path"))
544 q.options(FromCache("sql_cache_short", "repository_repo_path"))
545 return q.one().ui_value
545 return q.one().ui_value
546
546
547 @property
547 @property
548 def just_name(self):
548 def just_name(self):
549 return self.repo_name.split(Repository.url_sep())[-1]
549 return self.repo_name.split(Repository.url_sep())[-1]
550
550
551 @property
551 @property
552 def groups_with_parents(self):
552 def groups_with_parents(self):
553 groups = []
553 groups = []
554 if self.group is None:
554 if self.group is None:
555 return groups
555 return groups
556
556
557 cur_gr = self.group
557 cur_gr = self.group
558 groups.insert(0, cur_gr)
558 groups.insert(0, cur_gr)
559 while 1:
559 while 1:
560 gr = getattr(cur_gr, 'parent_group', None)
560 gr = getattr(cur_gr, 'parent_group', None)
561 cur_gr = cur_gr.parent_group
561 cur_gr = cur_gr.parent_group
562 if gr is None:
562 if gr is None:
563 break
563 break
564 groups.insert(0, gr)
564 groups.insert(0, gr)
565
565
566 return groups
566 return groups
567
567
568 @property
568 @property
569 def groups_and_repo(self):
569 def groups_and_repo(self):
570 return self.groups_with_parents, self.just_name
570 return self.groups_with_parents, self.just_name
571
571
572 @LazyProperty
572 @LazyProperty
573 def repo_path(self):
573 def repo_path(self):
574 """
574 """
575 Returns base full path for that repository means where it actually
575 Returns base full path for that repository means where it actually
576 exists on a filesystem
576 exists on a filesystem
577 """
577 """
578 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
578 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
579 Repository.url_sep())
579 Repository.url_sep())
580 q.options(FromCache("sql_cache_short", "repository_repo_path"))
580 q.options(FromCache("sql_cache_short", "repository_repo_path"))
581 return q.one().ui_value
581 return q.one().ui_value
582
582
583 @property
583 @property
584 def repo_full_path(self):
584 def repo_full_path(self):
585 p = [self.repo_path]
585 p = [self.repo_path]
586 # we need to split the name by / since this is how we store the
586 # we need to split the name by / since this is how we store the
587 # names in the database, but that eventually needs to be converted
587 # names in the database, but that eventually needs to be converted
588 # into a valid system path
588 # into a valid system path
589 p += self.repo_name.split(Repository.url_sep())
589 p += self.repo_name.split(Repository.url_sep())
590 return os.path.join(*p)
590 return os.path.join(*p)
591
591
592 def get_new_name(self, repo_name):
592 def get_new_name(self, repo_name):
593 """
593 """
594 returns new full repository name based on assigned group and new new
594 returns new full repository name based on assigned group and new new
595
595
596 :param group_name:
596 :param group_name:
597 """
597 """
598 path_prefix = self.group.full_path_splitted if self.group else []
598 path_prefix = self.group.full_path_splitted if self.group else []
599 return Repository.url_sep().join(path_prefix + [repo_name])
599 return Repository.url_sep().join(path_prefix + [repo_name])
600
600
601 @property
601 @property
602 def _ui(self):
602 def _ui(self):
603 """
603 """
604 Creates an db based ui object for this repository
604 Creates an db based ui object for this repository
605 """
605 """
606 from mercurial import ui
606 from mercurial import ui
607 from mercurial import config
607 from mercurial import config
608 baseui = ui.ui()
608 baseui = ui.ui()
609
609
610 #clean the baseui object
610 #clean the baseui object
611 baseui._ocfg = config.config()
611 baseui._ocfg = config.config()
612 baseui._ucfg = config.config()
612 baseui._ucfg = config.config()
613 baseui._tcfg = config.config()
613 baseui._tcfg = config.config()
614
614
615
615
616 ret = RhodeCodeUi.query()\
616 ret = RhodeCodeUi.query()\
617 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
617 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
618
618
619 hg_ui = ret
619 hg_ui = ret
620 for ui_ in hg_ui:
620 for ui_ in hg_ui:
621 if ui_.ui_active:
621 if ui_.ui_active:
622 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
622 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
623 ui_.ui_key, ui_.ui_value)
623 ui_.ui_key, ui_.ui_value)
624 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
624 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
625
625
626 return baseui
626 return baseui
627
627
628 @classmethod
628 @classmethod
629 def is_valid(cls, repo_name):
629 def is_valid(cls, repo_name):
630 """
630 """
631 returns True if given repo name is a valid filesystem repository
631 returns True if given repo name is a valid filesystem repository
632
632
633 @param cls:
633 @param cls:
634 @param repo_name:
634 @param repo_name:
635 """
635 """
636 from rhodecode.lib.utils import is_valid_repo
636 from rhodecode.lib.utils import is_valid_repo
637
637
638 return is_valid_repo(repo_name, cls.base_path())
638 return is_valid_repo(repo_name, cls.base_path())
639
639
640
640
641 #==========================================================================
641 #==========================================================================
642 # SCM PROPERTIES
642 # SCM PROPERTIES
643 #==========================================================================
643 #==========================================================================
644
644
645 def get_changeset(self, rev):
645 def get_changeset(self, rev):
646 return get_changeset_safe(self.scm_instance, rev)
646 return get_changeset_safe(self.scm_instance, rev)
647
647
648 @property
648 @property
649 def tip(self):
649 def tip(self):
650 return self.get_changeset('tip')
650 return self.get_changeset('tip')
651
651
652 @property
652 @property
653 def author(self):
653 def author(self):
654 return self.tip.author
654 return self.tip.author
655
655
656 @property
656 @property
657 def last_change(self):
657 def last_change(self):
658 return self.scm_instance.last_change
658 return self.scm_instance.last_change
659
659
660 #==========================================================================
660 #==========================================================================
661 # SCM CACHE INSTANCE
661 # SCM CACHE INSTANCE
662 #==========================================================================
662 #==========================================================================
663
663
664 @property
664 @property
665 def invalidate(self):
665 def invalidate(self):
666 """
666 return CacheInvalidation.invalidate(self.repo_name)
667 Returns Invalidation object if this repo should be invalidated
668 None otherwise. `cache_active = False` means that this cache
669 state is not valid and needs to be invalidated
670 """
671 return CacheInvalidation.query()\
672 .filter(CacheInvalidation.cache_key == self.repo_name)\
673 .filter(CacheInvalidation.cache_active == False)\
674 .scalar()
675
667
676 def set_invalidate(self):
668 def set_invalidate(self):
677 """
669 """
678 set a cache for invalidation for this instance
670 set a cache for invalidation for this instance
679 """
671 """
680 inv = CacheInvalidation.query()\
672 CacheInvalidation.set_invalidate(self.repo_name)
681 .filter(CacheInvalidation.cache_key == self.repo_name)\
682 .scalar()
683
684 if inv is None:
685 inv = CacheInvalidation(self.repo_name)
686 inv.cache_active = True
687 Session.add(inv)
688 Session.commit()
689
673
690 @LazyProperty
674 @LazyProperty
691 def scm_instance(self):
675 def scm_instance(self):
692 return self.__get_instance()
676 return self.__get_instance()
693
677
694 @property
678 @property
695 def scm_instance_cached(self):
679 def scm_instance_cached(self):
696 @cache_region('long_term')
680 @cache_region('long_term')
697 def _c(repo_name):
681 def _c(repo_name):
698 return self.__get_instance()
682 return self.__get_instance()
699
683 rn = self.repo_name
700 # TODO: remove this trick when beaker 1.6 is released
701 # and have fixed this issue with not supporting unicode keys
702 rn = safe_str(self.repo_name)
703
684
704 inv = self.invalidate
685 inv = self.invalidate
705 if inv is not None:
686 if inv is not None:
706 region_invalidate(_c, None, rn)
687 region_invalidate(_c, None, rn)
707 # update our cache
688 # update our cache
708 inv.cache_active = True
689 CacheInvalidation.set_valid(inv.cache_key)
709 Session.add(inv)
710 Session.commit()
711
712 return _c(rn)
690 return _c(rn)
713
691
714 def __get_instance(self):
692 def __get_instance(self):
715
693
716 repo_full_path = self.repo_full_path
694 repo_full_path = self.repo_full_path
717
695
718 try:
696 try:
719 alias = get_scm(repo_full_path)[0]
697 alias = get_scm(repo_full_path)[0]
720 log.debug('Creating instance of %s repository', alias)
698 log.debug('Creating instance of %s repository', alias)
721 backend = get_backend(alias)
699 backend = get_backend(alias)
722 except VCSError:
700 except VCSError:
723 log.error(traceback.format_exc())
701 log.error(traceback.format_exc())
724 log.error('Perhaps this repository is in db and not in '
702 log.error('Perhaps this repository is in db and not in '
725 'filesystem run rescan repositories with '
703 'filesystem run rescan repositories with '
726 '"destroy old data " option from admin panel')
704 '"destroy old data " option from admin panel')
727 return
705 return
728
706
729 if alias == 'hg':
707 if alias == 'hg':
730
708
731 repo = backend(safe_str(repo_full_path), create=False,
709 repo = backend(safe_str(repo_full_path), create=False,
732 baseui=self._ui)
710 baseui=self._ui)
733 #skip hidden web repository
711 # skip hidden web repository
734 if repo._get_hidden():
712 if repo._get_hidden():
735 return
713 return
736 else:
714 else:
737 repo = backend(repo_full_path, create=False)
715 repo = backend(repo_full_path, create=False)
738
716
739 return repo
717 return repo
740
718
741
719
742 class Group(Base, BaseModel):
720 class Group(Base, BaseModel):
743 __tablename__ = 'groups'
721 __tablename__ = 'groups'
744 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
722 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
745 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
723 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
746 __mapper_args__ = {'order_by':'group_name'}
724 __mapper_args__ = {'order_by':'group_name'}
747
725
748 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
726 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
749 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
727 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
750 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
728 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
751 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
729 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
752
730
753 parent_group = relationship('Group', remote_side=group_id)
731 parent_group = relationship('Group', remote_side=group_id)
754
732
755
733
756 def __init__(self, group_name='', parent_group=None):
734 def __init__(self, group_name='', parent_group=None):
757 self.group_name = group_name
735 self.group_name = group_name
758 self.parent_group = parent_group
736 self.parent_group = parent_group
759
737
760 def __repr__(self):
738 def __repr__(self):
761 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
739 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
762 self.group_name)
740 self.group_name)
763
741
764 @classmethod
742 @classmethod
765 def groups_choices(cls):
743 def groups_choices(cls):
766 from webhelpers.html import literal as _literal
744 from webhelpers.html import literal as _literal
767 repo_groups = [('', '')]
745 repo_groups = [('', '')]
768 sep = ' &raquo; '
746 sep = ' &raquo; '
769 _name = lambda k: _literal(sep.join(k))
747 _name = lambda k: _literal(sep.join(k))
770
748
771 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
749 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
772 for x in cls.query().all()])
750 for x in cls.query().all()])
773
751
774 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
752 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
775 return repo_groups
753 return repo_groups
776
754
777 @classmethod
755 @classmethod
778 def url_sep(cls):
756 def url_sep(cls):
779 return '/'
757 return '/'
780
758
781 @classmethod
759 @classmethod
782 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
760 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
783 if case_insensitive:
761 if case_insensitive:
784 gr = cls.query()\
762 gr = cls.query()\
785 .filter(cls.group_name.ilike(group_name))
763 .filter(cls.group_name.ilike(group_name))
786 else:
764 else:
787 gr = cls.query()\
765 gr = cls.query()\
788 .filter(cls.group_name == group_name)
766 .filter(cls.group_name == group_name)
789 if cache:
767 if cache:
790 gr = gr.options(FromCache("sql_cache_short",
768 gr = gr.options(FromCache("sql_cache_short",
791 "get_group_%s" % group_name))
769 "get_group_%s" % group_name))
792 return gr.scalar()
770 return gr.scalar()
793
771
794 @property
772 @property
795 def parents(self):
773 def parents(self):
796 parents_recursion_limit = 5
774 parents_recursion_limit = 5
797 groups = []
775 groups = []
798 if self.parent_group is None:
776 if self.parent_group is None:
799 return groups
777 return groups
800 cur_gr = self.parent_group
778 cur_gr = self.parent_group
801 groups.insert(0, cur_gr)
779 groups.insert(0, cur_gr)
802 cnt = 0
780 cnt = 0
803 while 1:
781 while 1:
804 cnt += 1
782 cnt += 1
805 gr = getattr(cur_gr, 'parent_group', None)
783 gr = getattr(cur_gr, 'parent_group', None)
806 cur_gr = cur_gr.parent_group
784 cur_gr = cur_gr.parent_group
807 if gr is None:
785 if gr is None:
808 break
786 break
809 if cnt == parents_recursion_limit:
787 if cnt == parents_recursion_limit:
810 # this will prevent accidental infinit loops
788 # this will prevent accidental infinit loops
811 log.error('group nested more than %s' %
789 log.error('group nested more than %s' %
812 parents_recursion_limit)
790 parents_recursion_limit)
813 break
791 break
814
792
815 groups.insert(0, gr)
793 groups.insert(0, gr)
816 return groups
794 return groups
817
795
818 @property
796 @property
819 def children(self):
797 def children(self):
820 return Group.query().filter(Group.parent_group == self)
798 return Group.query().filter(Group.parent_group == self)
821
799
822 @property
800 @property
823 def name(self):
801 def name(self):
824 return self.group_name.split(Group.url_sep())[-1]
802 return self.group_name.split(Group.url_sep())[-1]
825
803
826 @property
804 @property
827 def full_path(self):
805 def full_path(self):
828 return self.group_name
806 return self.group_name
829
807
830 @property
808 @property
831 def full_path_splitted(self):
809 def full_path_splitted(self):
832 return self.group_name.split(Group.url_sep())
810 return self.group_name.split(Group.url_sep())
833
811
834 @property
812 @property
835 def repositories(self):
813 def repositories(self):
836 return Repository.query().filter(Repository.group == self)
814 return Repository.query().filter(Repository.group == self)
837
815
838 @property
816 @property
839 def repositories_recursive_count(self):
817 def repositories_recursive_count(self):
840 cnt = self.repositories.count()
818 cnt = self.repositories.count()
841
819
842 def children_count(group):
820 def children_count(group):
843 cnt = 0
821 cnt = 0
844 for child in group.children:
822 for child in group.children:
845 cnt += child.repositories.count()
823 cnt += child.repositories.count()
846 cnt += children_count(child)
824 cnt += children_count(child)
847 return cnt
825 return cnt
848
826
849 return cnt + children_count(self)
827 return cnt + children_count(self)
850
828
851
829
852 def get_new_name(self, group_name):
830 def get_new_name(self, group_name):
853 """
831 """
854 returns new full group name based on parent and new name
832 returns new full group name based on parent and new name
855
833
856 :param group_name:
834 :param group_name:
857 """
835 """
858 path_prefix = (self.parent_group.full_path_splitted if
836 path_prefix = (self.parent_group.full_path_splitted if
859 self.parent_group else [])
837 self.parent_group else [])
860 return Group.url_sep().join(path_prefix + [group_name])
838 return Group.url_sep().join(path_prefix + [group_name])
861
839
862
840
863 class Permission(Base, BaseModel):
841 class Permission(Base, BaseModel):
864 __tablename__ = 'permissions'
842 __tablename__ = 'permissions'
865 __table_args__ = {'extend_existing':True}
843 __table_args__ = {'extend_existing':True}
866 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
844 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
867 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
845 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
868 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
846 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
869
847
870 def __repr__(self):
848 def __repr__(self):
871 return "<%s('%s:%s')>" % (self.__class__.__name__,
849 return "<%s('%s:%s')>" % (self.__class__.__name__,
872 self.permission_id, self.permission_name)
850 self.permission_id, self.permission_name)
873
851
874 @classmethod
852 @classmethod
875 def get_by_key(cls, key):
853 def get_by_key(cls, key):
876 return cls.query().filter(cls.permission_name == key).scalar()
854 return cls.query().filter(cls.permission_name == key).scalar()
877
855
878 class RepoToPerm(Base, BaseModel):
856 class RepoToPerm(Base, BaseModel):
879 __tablename__ = 'repo_to_perm'
857 __tablename__ = 'repo_to_perm'
880 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
858 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
881 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
859 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
882 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
860 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
883 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
861 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
884 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
862 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
885
863
886 user = relationship('User')
864 user = relationship('User')
887 permission = relationship('Permission')
865 permission = relationship('Permission')
888 repository = relationship('Repository')
866 repository = relationship('Repository')
889
867
890 class UserToPerm(Base, BaseModel):
868 class UserToPerm(Base, BaseModel):
891 __tablename__ = 'user_to_perm'
869 __tablename__ = 'user_to_perm'
892 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
870 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
893 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
871 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
894 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
872 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
895 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
873 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
896
874
897 user = relationship('User')
875 user = relationship('User')
898 permission = relationship('Permission')
876 permission = relationship('Permission')
899
877
900 @classmethod
878 @classmethod
901 def has_perm(cls, user_id, perm):
879 def has_perm(cls, user_id, perm):
902 if not isinstance(perm, Permission):
880 if not isinstance(perm, Permission):
903 raise Exception('perm needs to be an instance of Permission class')
881 raise Exception('perm needs to be an instance of Permission class')
904
882
905 return cls.query().filter(cls.user_id == user_id)\
883 return cls.query().filter(cls.user_id == user_id)\
906 .filter(cls.permission == perm).scalar() is not None
884 .filter(cls.permission == perm).scalar() is not None
907
885
908 @classmethod
886 @classmethod
909 def grant_perm(cls, user_id, perm):
887 def grant_perm(cls, user_id, perm):
910 if not isinstance(perm, Permission):
888 if not isinstance(perm, Permission):
911 raise Exception('perm needs to be an instance of Permission class')
889 raise Exception('perm needs to be an instance of Permission class')
912
890
913 new = cls()
891 new = cls()
914 new.user_id = user_id
892 new.user_id = user_id
915 new.permission = perm
893 new.permission = perm
916 try:
894 try:
917 Session.add(new)
895 Session.add(new)
918 Session.commit()
896 Session.commit()
919 except:
897 except:
920 Session.rollback()
898 Session.rollback()
921
899
922
900
923 @classmethod
901 @classmethod
924 def revoke_perm(cls, user_id, perm):
902 def revoke_perm(cls, user_id, perm):
925 if not isinstance(perm, Permission):
903 if not isinstance(perm, Permission):
926 raise Exception('perm needs to be an instance of Permission class')
904 raise Exception('perm needs to be an instance of Permission class')
927
905
928 try:
906 try:
929 cls.query().filter(cls.user_id == user_id)\
907 cls.query().filter(cls.user_id == user_id)\
930 .filter(cls.permission == perm).delete()
908 .filter(cls.permission == perm).delete()
931 Session.commit()
909 Session.commit()
932 except:
910 except:
933 Session.rollback()
911 Session.rollback()
934
912
935 class UsersGroupRepoToPerm(Base, BaseModel):
913 class UsersGroupRepoToPerm(Base, BaseModel):
936 __tablename__ = 'users_group_repo_to_perm'
914 __tablename__ = 'users_group_repo_to_perm'
937 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
915 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
938 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
916 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
939 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
917 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
940 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
918 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
941 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
919 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
942
920
943 users_group = relationship('UsersGroup')
921 users_group = relationship('UsersGroup')
944 permission = relationship('Permission')
922 permission = relationship('Permission')
945 repository = relationship('Repository')
923 repository = relationship('Repository')
946
924
947 def __repr__(self):
925 def __repr__(self):
948 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
926 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
949
927
950 class UsersGroupToPerm(Base, BaseModel):
928 class UsersGroupToPerm(Base, BaseModel):
951 __tablename__ = 'users_group_to_perm'
929 __tablename__ = 'users_group_to_perm'
952 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
930 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
953 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
931 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
954 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
932 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
955
933
956 users_group = relationship('UsersGroup')
934 users_group = relationship('UsersGroup')
957 permission = relationship('Permission')
935 permission = relationship('Permission')
958
936
959
937
960 @classmethod
938 @classmethod
961 def has_perm(cls, users_group_id, perm):
939 def has_perm(cls, users_group_id, perm):
962 if not isinstance(perm, Permission):
940 if not isinstance(perm, Permission):
963 raise Exception('perm needs to be an instance of Permission class')
941 raise Exception('perm needs to be an instance of Permission class')
964
942
965 return cls.query().filter(cls.users_group_id ==
943 return cls.query().filter(cls.users_group_id ==
966 users_group_id)\
944 users_group_id)\
967 .filter(cls.permission == perm)\
945 .filter(cls.permission == perm)\
968 .scalar() is not None
946 .scalar() is not None
969
947
970 @classmethod
948 @classmethod
971 def grant_perm(cls, users_group_id, perm):
949 def grant_perm(cls, users_group_id, perm):
972 if not isinstance(perm, Permission):
950 if not isinstance(perm, Permission):
973 raise Exception('perm needs to be an instance of Permission class')
951 raise Exception('perm needs to be an instance of Permission class')
974
952
975 new = cls()
953 new = cls()
976 new.users_group_id = users_group_id
954 new.users_group_id = users_group_id
977 new.permission = perm
955 new.permission = perm
978 try:
956 try:
979 Session.add(new)
957 Session.add(new)
980 Session.commit()
958 Session.commit()
981 except:
959 except:
982 Session.rollback()
960 Session.rollback()
983
961
984
962
985 @classmethod
963 @classmethod
986 def revoke_perm(cls, users_group_id, perm):
964 def revoke_perm(cls, users_group_id, perm):
987 if not isinstance(perm, Permission):
965 if not isinstance(perm, Permission):
988 raise Exception('perm needs to be an instance of Permission class')
966 raise Exception('perm needs to be an instance of Permission class')
989
967
990 try:
968 try:
991 cls.query().filter(cls.users_group_id == users_group_id)\
969 cls.query().filter(cls.users_group_id == users_group_id)\
992 .filter(cls.permission == perm).delete()
970 .filter(cls.permission == perm).delete()
993 Session.commit()
971 Session.commit()
994 except:
972 except:
995 Session.rollback()
973 Session.rollback()
996
974
997
975
998 class GroupToPerm(Base, BaseModel):
976 class GroupToPerm(Base, BaseModel):
999 __tablename__ = 'group_to_perm'
977 __tablename__ = 'group_to_perm'
1000 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
978 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
1001
979
1002 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
980 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1003 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
981 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1004 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
982 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1005 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
983 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1006
984
1007 user = relationship('User')
985 user = relationship('User')
1008 permission = relationship('Permission')
986 permission = relationship('Permission')
1009 group = relationship('Group')
987 group = relationship('Group')
1010
988
1011 class Statistics(Base, BaseModel):
989 class Statistics(Base, BaseModel):
1012 __tablename__ = 'statistics'
990 __tablename__ = 'statistics'
1013 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
991 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
1014 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
992 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1015 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
993 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1016 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
994 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1017 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
995 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1018 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
996 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1019 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
997 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1020
998
1021 repository = relationship('Repository', single_parent=True)
999 repository = relationship('Repository', single_parent=True)
1022
1000
1023 class UserFollowing(Base, BaseModel):
1001 class UserFollowing(Base, BaseModel):
1024 __tablename__ = 'user_followings'
1002 __tablename__ = 'user_followings'
1025 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
1003 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
1026 UniqueConstraint('user_id', 'follows_user_id')
1004 UniqueConstraint('user_id', 'follows_user_id')
1027 , {'extend_existing':True})
1005 , {'extend_existing':True})
1028
1006
1029 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1007 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1030 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1008 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1031 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1009 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1032 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1010 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1033 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1011 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1034
1012
1035 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1013 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1036
1014
1037 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1015 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1038 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1016 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1039
1017
1040
1018
1041 @classmethod
1019 @classmethod
1042 def get_repo_followers(cls, repo_id):
1020 def get_repo_followers(cls, repo_id):
1043 return cls.query().filter(cls.follows_repo_id == repo_id)
1021 return cls.query().filter(cls.follows_repo_id == repo_id)
1044
1022
1045 class CacheInvalidation(Base, BaseModel):
1023 class CacheInvalidation(Base, BaseModel):
1046 __tablename__ = 'cache_invalidation'
1024 __tablename__ = 'cache_invalidation'
1047 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
1025 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
1048 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1026 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1049 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1027 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1050 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1028 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1051 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1029 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1052
1030
1053
1031
1054 def __init__(self, cache_key, cache_args=''):
1032 def __init__(self, cache_key, cache_args=''):
1055 self.cache_key = cache_key
1033 self.cache_key = cache_key
1056 self.cache_args = cache_args
1034 self.cache_args = cache_args
1057 self.cache_active = False
1035 self.cache_active = False
1058
1036
1059 def __repr__(self):
1037 def __repr__(self):
1060 return "<%s('%s:%s')>" % (self.__class__.__name__,
1038 return "<%s('%s:%s')>" % (self.__class__.__name__,
1061 self.cache_id, self.cache_key)
1039 self.cache_id, self.cache_key)
1062
1040
1041 @classmethod
1042 def invalidate(cls, key):
1043 """
1044 Returns Invalidation object if this given key should be invalidated
1045 None otherwise. `cache_active = False` means that this cache
1046 state is not valid and needs to be invalidated
1047
1048 :param key:
1049 """
1050 return cls.query()\
1051 .filter(CacheInvalidation.cache_key == key)\
1052 .filter(CacheInvalidation.cache_active == False)\
1053 .scalar()
1054
1055 @classmethod
1056 def set_invalidate(cls, key):
1057 """
1058 Mark this Cache key for invalidation
1059
1060 :param key:
1061 """
1062
1063 log.debug('marking %s for invalidation' % key)
1064 inv_obj = Session().query(cls)\
1065 .filter(cls.cache_key == key).scalar()
1066 if inv_obj:
1067 inv_obj.cache_active = False
1068 else:
1069 log.debug('cache key not found in invalidation db -> creating one')
1070 inv_obj = CacheInvalidation(key)
1071
1072 try:
1073 Session.add(inv_obj)
1074 Session.commit()
1075 except Exception:
1076 log.error(traceback.format_exc())
1077 Session.rollback()
1078
1079 @classmethod
1080 def set_valid(cls, key):
1081 """
1082 Mark this cache key as active and currently cached
1083
1084 :param key:
1085 """
1086 inv_obj = Session().query(CacheInvalidation)\
1087 .filter(CacheInvalidation.cache_key == key).scalar()
1088 inv_obj.cache_active = True
1089 Session.add(inv_obj)
1090 Session.commit()
1091
1063 class DbMigrateVersion(Base, BaseModel):
1092 class DbMigrateVersion(Base, BaseModel):
1064 __tablename__ = 'db_migrate_version'
1093 __tablename__ = 'db_migrate_version'
1065 __table_args__ = {'extend_existing':True}
1094 __table_args__ = {'extend_existing':True}
1066 repository_id = Column('repository_id', String(250), primary_key=True)
1095 repository_id = Column('repository_id', String(250), primary_key=True)
1067 repository_path = Column('repository_path', Text)
1096 repository_path = Column('repository_path', Text)
1068 version = Column('version', Integer)
1097 version = Column('version', Integer)
1069
1098
@@ -1,414 +1,383 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.scm
3 rhodecode.model.scm
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Scm model for RhodeCode
6 Scm model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import time
26 import time
27 import traceback
27 import traceback
28 import logging
28 import logging
29
29
30 from sqlalchemy.exc import DatabaseError
30 from sqlalchemy.exc import DatabaseError
31
31
32 from vcs import get_backend
32 from vcs import get_backend
33 from vcs.exceptions import RepositoryError
33 from vcs.exceptions import RepositoryError
34 from vcs.utils.lazy import LazyProperty
34 from vcs.utils.lazy import LazyProperty
35 from vcs.nodes import FileNode
35 from vcs.nodes import FileNode
36
36
37 from rhodecode import BACKENDS
37 from rhodecode import BACKENDS
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib import safe_str
39 from rhodecode.lib import safe_str
40 from rhodecode.lib.auth import HasRepoPermissionAny
40 from rhodecode.lib.auth import HasRepoPermissionAny
41 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
41 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
42 action_logger, EmptyChangeset
42 action_logger, EmptyChangeset
43 from rhodecode.model import BaseModel
43 from rhodecode.model import BaseModel
44 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
44 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
45 UserFollowing, UserLog, User
45 UserFollowing, UserLog, User
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class UserTemp(object):
50 class UserTemp(object):
51 def __init__(self, user_id):
51 def __init__(self, user_id):
52 self.user_id = user_id
52 self.user_id = user_id
53
53
54 def __repr__(self):
54 def __repr__(self):
55 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
55 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
56
56
57
57
58 class RepoTemp(object):
58 class RepoTemp(object):
59 def __init__(self, repo_id):
59 def __init__(self, repo_id):
60 self.repo_id = repo_id
60 self.repo_id = repo_id
61
61
62 def __repr__(self):
62 def __repr__(self):
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
64
64
65 class CachedRepoList(object):
65 class CachedRepoList(object):
66
66
67 def __init__(self, db_repo_list, repos_path, order_by=None):
67 def __init__(self, db_repo_list, repos_path, order_by=None):
68 self.db_repo_list = db_repo_list
68 self.db_repo_list = db_repo_list
69 self.repos_path = repos_path
69 self.repos_path = repos_path
70 self.order_by = order_by
70 self.order_by = order_by
71 self.reversed = (order_by or '').startswith('-')
71 self.reversed = (order_by or '').startswith('-')
72
72
73 def __len__(self):
73 def __len__(self):
74 return len(self.db_repo_list)
74 return len(self.db_repo_list)
75
75
76 def __repr__(self):
76 def __repr__(self):
77 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
77 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
78
78
79 def __iter__(self):
79 def __iter__(self):
80 for dbr in self.db_repo_list:
80 for dbr in self.db_repo_list:
81
81
82 scmr = dbr.scm_instance_cached
82 scmr = dbr.scm_instance_cached
83
83
84 # check permission at this level
84 # check permission at this level
85 if not HasRepoPermissionAny('repository.read', 'repository.write',
85 if not HasRepoPermissionAny('repository.read', 'repository.write',
86 'repository.admin')(dbr.repo_name,
86 'repository.admin')(dbr.repo_name,
87 'get repo check'):
87 'get repo check'):
88 continue
88 continue
89
89
90 if scmr is None:
90 if scmr is None:
91 log.error('%s this repository is present in database but it '
91 log.error('%s this repository is present in database but it '
92 'cannot be created as an scm instance',
92 'cannot be created as an scm instance',
93 dbr.repo_name)
93 dbr.repo_name)
94 continue
94 continue
95
95
96 last_change = scmr.last_change
96 last_change = scmr.last_change
97 tip = h.get_changeset_safe(scmr, 'tip')
97 tip = h.get_changeset_safe(scmr, 'tip')
98
98
99 tmp_d = {}
99 tmp_d = {}
100 tmp_d['name'] = dbr.repo_name
100 tmp_d['name'] = dbr.repo_name
101 tmp_d['name_sort'] = tmp_d['name'].lower()
101 tmp_d['name_sort'] = tmp_d['name'].lower()
102 tmp_d['description'] = dbr.description
102 tmp_d['description'] = dbr.description
103 tmp_d['description_sort'] = tmp_d['description']
103 tmp_d['description_sort'] = tmp_d['description']
104 tmp_d['last_change'] = last_change
104 tmp_d['last_change'] = last_change
105 tmp_d['last_change_sort'] = time.mktime(last_change \
105 tmp_d['last_change_sort'] = time.mktime(last_change \
106 .timetuple())
106 .timetuple())
107 tmp_d['tip'] = tip.raw_id
107 tmp_d['tip'] = tip.raw_id
108 tmp_d['tip_sort'] = tip.revision
108 tmp_d['tip_sort'] = tip.revision
109 tmp_d['rev'] = tip.revision
109 tmp_d['rev'] = tip.revision
110 tmp_d['contact'] = dbr.user.full_contact
110 tmp_d['contact'] = dbr.user.full_contact
111 tmp_d['contact_sort'] = tmp_d['contact']
111 tmp_d['contact_sort'] = tmp_d['contact']
112 tmp_d['owner_sort'] = tmp_d['contact']
112 tmp_d['owner_sort'] = tmp_d['contact']
113 tmp_d['repo_archives'] = list(scmr._get_archives())
113 tmp_d['repo_archives'] = list(scmr._get_archives())
114 tmp_d['last_msg'] = tip.message
114 tmp_d['last_msg'] = tip.message
115 tmp_d['author'] = tip.author
115 tmp_d['author'] = tip.author
116 tmp_d['dbrepo'] = dbr.get_dict()
116 tmp_d['dbrepo'] = dbr.get_dict()
117 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
117 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
118 else {}
118 else {}
119 yield tmp_d
119 yield tmp_d
120
120
121 class ScmModel(BaseModel):
121 class ScmModel(BaseModel):
122 """Generic Scm Model
122 """Generic Scm Model
123 """
123 """
124
124
125 @LazyProperty
125 @LazyProperty
126 def repos_path(self):
126 def repos_path(self):
127 """Get's the repositories root path from database
127 """Get's the repositories root path from database
128 """
128 """
129
129
130 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
130 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
131
131
132 return q.ui_value
132 return q.ui_value
133
133
134 def repo_scan(self, repos_path=None):
134 def repo_scan(self, repos_path=None):
135 """Listing of repositories in given path. This path should not be a
135 """Listing of repositories in given path. This path should not be a
136 repository itself. Return a dictionary of repository objects
136 repository itself. Return a dictionary of repository objects
137
137
138 :param repos_path: path to directory containing repositories
138 :param repos_path: path to directory containing repositories
139 """
139 """
140
140
141 log.info('scanning for repositories in %s', repos_path)
141 log.info('scanning for repositories in %s', repos_path)
142
142
143 if repos_path is None:
143 if repos_path is None:
144 repos_path = self.repos_path
144 repos_path = self.repos_path
145
145
146 baseui = make_ui('db')
146 baseui = make_ui('db')
147 repos_list = {}
147 repos_list = {}
148
148
149 for name, path in get_filesystem_repos(repos_path, recursive=True):
149 for name, path in get_filesystem_repos(repos_path, recursive=True):
150
150
151 # name need to be decomposed and put back together using the /
151 # name need to be decomposed and put back together using the /
152 # since this is internal storage separator for rhodecode
152 # since this is internal storage separator for rhodecode
153 name = Repository.url_sep().join(name.split(os.sep))
153 name = Repository.url_sep().join(name.split(os.sep))
154
154
155 try:
155 try:
156 if name in repos_list:
156 if name in repos_list:
157 raise RepositoryError('Duplicate repository name %s '
157 raise RepositoryError('Duplicate repository name %s '
158 'found in %s' % (name, path))
158 'found in %s' % (name, path))
159 else:
159 else:
160
160
161 klass = get_backend(path[0])
161 klass = get_backend(path[0])
162
162
163 if path[0] == 'hg' and path[0] in BACKENDS.keys():
163 if path[0] == 'hg' and path[0] in BACKENDS.keys():
164
164
165 # for mercurial we need to have an str path
165 # for mercurial we need to have an str path
166 repos_list[name] = klass(safe_str(path[1]),
166 repos_list[name] = klass(safe_str(path[1]),
167 baseui=baseui)
167 baseui=baseui)
168
168
169 if path[0] == 'git' and path[0] in BACKENDS.keys():
169 if path[0] == 'git' and path[0] in BACKENDS.keys():
170 repos_list[name] = klass(path[1])
170 repos_list[name] = klass(path[1])
171 except OSError:
171 except OSError:
172 continue
172 continue
173
173
174 return repos_list
174 return repos_list
175
175
176 def get_repos(self, all_repos=None, sort_key=None):
176 def get_repos(self, all_repos=None, sort_key=None):
177 """
177 """
178 Get all repos from db and for each repo create it's
178 Get all repos from db and for each repo create it's
179 backend instance and fill that backed with information from database
179 backend instance and fill that backed with information from database
180
180
181 :param all_repos: list of repository names as strings
181 :param all_repos: list of repository names as strings
182 give specific repositories list, good for filtering
182 give specific repositories list, good for filtering
183 """
183 """
184 if all_repos is None:
184 if all_repos is None:
185 all_repos = self.sa.query(Repository)\
185 all_repos = self.sa.query(Repository)\
186 .filter(Repository.group_id == None)\
186 .filter(Repository.group_id == None)\
187 .order_by(Repository.repo_name).all()
187 .order_by(Repository.repo_name).all()
188
188
189 repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path,
189 repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path,
190 order_by=sort_key)
190 order_by=sort_key)
191
191
192 return repo_iter
192 return repo_iter
193
193
194 def mark_for_invalidation(self, repo_name):
194 def mark_for_invalidation(self, repo_name):
195 """Puts cache invalidation task into db for
195 """Puts cache invalidation task into db for
196 further global cache invalidation
196 further global cache invalidation
197
197
198 :param repo_name: this repo that should invalidation take place
198 :param repo_name: this repo that should invalidation take place
199 """
199 """
200
200 CacheInvalidation.set_invalidate(repo_name)
201 log.debug('marking %s for invalidation', repo_name)
201 CacheInvalidation.set_invalidate(repo_name+"_README")
202 cache = self.sa.query(CacheInvalidation)\
203 .filter(CacheInvalidation.cache_key == repo_name).scalar()
204
205 if cache:
206 # mark this cache as inactive
207 cache.cache_active = False
208 else:
209 log.debug('cache key not found in invalidation db -> creating one')
210 cache = CacheInvalidation(repo_name)
211
212 try:
213 self.sa.add(cache)
214 self.sa.commit()
215 except (DatabaseError,):
216 log.error(traceback.format_exc())
217 self.sa.rollback()
218
202
219 def toggle_following_repo(self, follow_repo_id, user_id):
203 def toggle_following_repo(self, follow_repo_id, user_id):
220
204
221 f = self.sa.query(UserFollowing)\
205 f = self.sa.query(UserFollowing)\
222 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
206 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
223 .filter(UserFollowing.user_id == user_id).scalar()
207 .filter(UserFollowing.user_id == user_id).scalar()
224
208
225 if f is not None:
209 if f is not None:
226
210
227 try:
211 try:
228 self.sa.delete(f)
212 self.sa.delete(f)
229 self.sa.commit()
213 self.sa.commit()
230 action_logger(UserTemp(user_id),
214 action_logger(UserTemp(user_id),
231 'stopped_following_repo',
215 'stopped_following_repo',
232 RepoTemp(follow_repo_id))
216 RepoTemp(follow_repo_id))
233 return
217 return
234 except:
218 except:
235 log.error(traceback.format_exc())
219 log.error(traceback.format_exc())
236 self.sa.rollback()
220 self.sa.rollback()
237 raise
221 raise
238
222
239 try:
223 try:
240 f = UserFollowing()
224 f = UserFollowing()
241 f.user_id = user_id
225 f.user_id = user_id
242 f.follows_repo_id = follow_repo_id
226 f.follows_repo_id = follow_repo_id
243 self.sa.add(f)
227 self.sa.add(f)
244 self.sa.commit()
228 self.sa.commit()
245 action_logger(UserTemp(user_id),
229 action_logger(UserTemp(user_id),
246 'started_following_repo',
230 'started_following_repo',
247 RepoTemp(follow_repo_id))
231 RepoTemp(follow_repo_id))
248 except:
232 except:
249 log.error(traceback.format_exc())
233 log.error(traceback.format_exc())
250 self.sa.rollback()
234 self.sa.rollback()
251 raise
235 raise
252
236
253 def toggle_following_user(self, follow_user_id, user_id):
237 def toggle_following_user(self, follow_user_id, user_id):
254 f = self.sa.query(UserFollowing)\
238 f = self.sa.query(UserFollowing)\
255 .filter(UserFollowing.follows_user_id == follow_user_id)\
239 .filter(UserFollowing.follows_user_id == follow_user_id)\
256 .filter(UserFollowing.user_id == user_id).scalar()
240 .filter(UserFollowing.user_id == user_id).scalar()
257
241
258 if f is not None:
242 if f is not None:
259 try:
243 try:
260 self.sa.delete(f)
244 self.sa.delete(f)
261 self.sa.commit()
245 self.sa.commit()
262 return
246 return
263 except:
247 except:
264 log.error(traceback.format_exc())
248 log.error(traceback.format_exc())
265 self.sa.rollback()
249 self.sa.rollback()
266 raise
250 raise
267
251
268 try:
252 try:
269 f = UserFollowing()
253 f = UserFollowing()
270 f.user_id = user_id
254 f.user_id = user_id
271 f.follows_user_id = follow_user_id
255 f.follows_user_id = follow_user_id
272 self.sa.add(f)
256 self.sa.add(f)
273 self.sa.commit()
257 self.sa.commit()
274 except:
258 except:
275 log.error(traceback.format_exc())
259 log.error(traceback.format_exc())
276 self.sa.rollback()
260 self.sa.rollback()
277 raise
261 raise
278
262
279 def is_following_repo(self, repo_name, user_id, cache=False):
263 def is_following_repo(self, repo_name, user_id, cache=False):
280 r = self.sa.query(Repository)\
264 r = self.sa.query(Repository)\
281 .filter(Repository.repo_name == repo_name).scalar()
265 .filter(Repository.repo_name == repo_name).scalar()
282
266
283 f = self.sa.query(UserFollowing)\
267 f = self.sa.query(UserFollowing)\
284 .filter(UserFollowing.follows_repository == r)\
268 .filter(UserFollowing.follows_repository == r)\
285 .filter(UserFollowing.user_id == user_id).scalar()
269 .filter(UserFollowing.user_id == user_id).scalar()
286
270
287 return f is not None
271 return f is not None
288
272
289 def is_following_user(self, username, user_id, cache=False):
273 def is_following_user(self, username, user_id, cache=False):
290 u = User.get_by_username(username)
274 u = User.get_by_username(username)
291
275
292 f = self.sa.query(UserFollowing)\
276 f = self.sa.query(UserFollowing)\
293 .filter(UserFollowing.follows_user == u)\
277 .filter(UserFollowing.follows_user == u)\
294 .filter(UserFollowing.user_id == user_id).scalar()
278 .filter(UserFollowing.user_id == user_id).scalar()
295
279
296 return f is not None
280 return f is not None
297
281
298 def get_followers(self, repo_id):
282 def get_followers(self, repo_id):
299 if not isinstance(repo_id, int):
283 if not isinstance(repo_id, int):
300 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
284 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
301
285
302 return self.sa.query(UserFollowing)\
286 return self.sa.query(UserFollowing)\
303 .filter(UserFollowing.follows_repo_id == repo_id).count()
287 .filter(UserFollowing.follows_repo_id == repo_id).count()
304
288
305 def get_forks(self, repo_id):
289 def get_forks(self, repo_id):
306 if not isinstance(repo_id, int):
290 if not isinstance(repo_id, int):
307 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
291 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
308
292
309 return self.sa.query(Repository)\
293 return self.sa.query(Repository)\
310 .filter(Repository.fork_id == repo_id).count()
294 .filter(Repository.fork_id == repo_id).count()
311
295
312 def pull_changes(self, repo_name, username):
296 def pull_changes(self, repo_name, username):
313 dbrepo = Repository.get_by_repo_name(repo_name)
297 dbrepo = Repository.get_by_repo_name(repo_name)
314 clone_uri = dbrepo.clone_uri
298 clone_uri = dbrepo.clone_uri
315 if not clone_uri:
299 if not clone_uri:
316 raise Exception("This repository doesn't have a clone uri")
300 raise Exception("This repository doesn't have a clone uri")
317
301
318 repo = dbrepo.scm_instance
302 repo = dbrepo.scm_instance
319 try:
303 try:
320 extras = {'ip': '',
304 extras = {'ip': '',
321 'username': username,
305 'username': username,
322 'action': 'push_remote',
306 'action': 'push_remote',
323 'repository': repo_name}
307 'repository': repo_name}
324
308
325 #inject ui extra param to log this action via push logger
309 #inject ui extra param to log this action via push logger
326 for k, v in extras.items():
310 for k, v in extras.items():
327 repo._repo.ui.setconfig('rhodecode_extras', k, v)
311 repo._repo.ui.setconfig('rhodecode_extras', k, v)
328
312
329 repo.pull(clone_uri)
313 repo.pull(clone_uri)
330 self.mark_for_invalidation(repo_name)
314 self.mark_for_invalidation(repo_name)
331 except:
315 except:
332 log.error(traceback.format_exc())
316 log.error(traceback.format_exc())
333 raise
317 raise
334
318
335 def commit_change(self, repo, repo_name, cs, user, author, message, content,
319 def commit_change(self, repo, repo_name, cs, user, author, message, content,
336 f_path):
320 f_path):
337
321
338 if repo.alias == 'hg':
322 if repo.alias == 'hg':
339 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
323 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
340 elif repo.alias == 'git':
324 elif repo.alias == 'git':
341 from vcs.backends.git import GitInMemoryChangeset as IMC
325 from vcs.backends.git import GitInMemoryChangeset as IMC
342
326
343 # decoding here will force that we have proper encoded values
327 # decoding here will force that we have proper encoded values
344 # in any other case this will throw exceptions and deny commit
328 # in any other case this will throw exceptions and deny commit
345 content = safe_str(content)
329 content = safe_str(content)
346 message = safe_str(message)
330 message = safe_str(message)
347 path = safe_str(f_path)
331 path = safe_str(f_path)
348 author = safe_str(author)
332 author = safe_str(author)
349 m = IMC(repo)
333 m = IMC(repo)
350 m.change(FileNode(path, content))
334 m.change(FileNode(path, content))
351 tip = m.commit(message=message,
335 tip = m.commit(message=message,
352 author=author,
336 author=author,
353 parents=[cs], branch=cs.branch)
337 parents=[cs], branch=cs.branch)
354
338
355 new_cs = tip.short_id
339 new_cs = tip.short_id
356 action = 'push_local:%s' % new_cs
340 action = 'push_local:%s' % new_cs
357
341
358 action_logger(user, action, repo_name)
342 action_logger(user, action, repo_name)
359
343
360 self.mark_for_invalidation(repo_name)
344 self.mark_for_invalidation(repo_name)
361
345
362 def create_node(self, repo, repo_name, cs, user, author, message, content,
346 def create_node(self, repo, repo_name, cs, user, author, message, content,
363 f_path):
347 f_path):
364 if repo.alias == 'hg':
348 if repo.alias == 'hg':
365 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
349 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
366 elif repo.alias == 'git':
350 elif repo.alias == 'git':
367 from vcs.backends.git import GitInMemoryChangeset as IMC
351 from vcs.backends.git import GitInMemoryChangeset as IMC
368 # decoding here will force that we have proper encoded values
352 # decoding here will force that we have proper encoded values
369 # in any other case this will throw exceptions and deny commit
353 # in any other case this will throw exceptions and deny commit
370
354
371 if isinstance(content, (basestring,)):
355 if isinstance(content, (basestring,)):
372 content = safe_str(content)
356 content = safe_str(content)
373 elif isinstance(content, file):
357 elif isinstance(content, file):
374 content = content.read()
358 content = content.read()
375
359
376 message = safe_str(message)
360 message = safe_str(message)
377 path = safe_str(f_path)
361 path = safe_str(f_path)
378 author = safe_str(author)
362 author = safe_str(author)
379 m = IMC(repo)
363 m = IMC(repo)
380
364
381 if isinstance(cs, EmptyChangeset):
365 if isinstance(cs, EmptyChangeset):
382 # Emptychangeset means we we're editing empty repository
366 # Emptychangeset means we we're editing empty repository
383 parents = None
367 parents = None
384 else:
368 else:
385 parents = [cs]
369 parents = [cs]
386
370
387 m.add(FileNode(path, content=content))
371 m.add(FileNode(path, content=content))
388 tip = m.commit(message=message,
372 tip = m.commit(message=message,
389 author=author,
373 author=author,
390 parents=parents, branch=cs.branch)
374 parents=parents, branch=cs.branch)
391 new_cs = tip.short_id
375 new_cs = tip.short_id
392 action = 'push_local:%s' % new_cs
376 action = 'push_local:%s' % new_cs
393
377
394 action_logger(user, action, repo_name)
378 action_logger(user, action, repo_name)
395
379
396 self.mark_for_invalidation(repo_name)
380 self.mark_for_invalidation(repo_name)
397
381
398
399 def get_unread_journal(self):
382 def get_unread_journal(self):
400 return self.sa.query(UserLog).count()
383 return self.sa.query(UserLog).count()
401
402 def _should_invalidate(self, repo_name):
403 """Looks up database for invalidation signals for this repo_name
404
405 :param repo_name:
406 """
407
408 ret = self.sa.query(CacheInvalidation)\
409 .filter(CacheInvalidation.cache_key == repo_name)\
410 .filter(CacheInvalidation.cache_active == False)\
411 .scalar()
412
413 return ret
414
@@ -1,221 +1,227 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
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27
27
28 [server:main]
28 [server:main]
29 ##nr of threads to spawn
29 ##nr of threads to spawn
30 threadpool_workers = 5
30 threadpool_workers = 5
31
31
32 ##max request before thread respawn
32 ##max request before thread respawn
33 threadpool_max_requests = 2
33 threadpool_max_requests = 2
34
34
35 ##option to use threads of process
35 ##option to use threads of process
36 use_threadpool = true
36 use_threadpool = true
37
37
38 use = egg:Paste#http
38 use = egg:Paste#http
39 host = 127.0.0.1
39 host = 127.0.0.1
40 port = 5000
40 port = 5000
41
41
42 [app:main]
42 [app:main]
43 use = egg:rhodecode
43 use = egg:rhodecode
44 full_stack = true
44 full_stack = true
45 static_files = true
45 static_files = true
46 lang=en
46 lang=en
47 cache_dir = /tmp/data
47 cache_dir = /tmp/data
48 index_dir = /tmp/index
48 index_dir = /tmp/index
49 app_instance_uuid = develop-test
49 app_instance_uuid = develop-test
50 cut_off_limit = 256000
50 cut_off_limit = 256000
51 force_https = false
51 force_https = false
52 commit_parse_limit = 25
52 commit_parse_limit = 25
53 use_gravatar = true
53 use_gravatar = true
54
54
55 ####################################
55 ####################################
56 ### CELERY CONFIG ####
56 ### CELERY CONFIG ####
57 ####################################
57 ####################################
58 use_celery = false
58 use_celery = false
59 broker.host = localhost
59 broker.host = localhost
60 broker.vhost = rabbitmqhost
60 broker.vhost = rabbitmqhost
61 broker.port = 5672
61 broker.port = 5672
62 broker.user = rabbitmq
62 broker.user = rabbitmq
63 broker.password = qweqwe
63 broker.password = qweqwe
64
64
65 celery.imports = rhodecode.lib.celerylib.tasks
65 celery.imports = rhodecode.lib.celerylib.tasks
66
66
67 celery.result.backend = amqp
67 celery.result.backend = amqp
68 celery.result.dburi = amqp://
68 celery.result.dburi = amqp://
69 celery.result.serialier = json
69 celery.result.serialier = json
70
70
71 #celery.send.task.error.emails = true
71 #celery.send.task.error.emails = true
72 #celery.amqp.task.result.expires = 18000
72 #celery.amqp.task.result.expires = 18000
73
73
74 celeryd.concurrency = 2
74 celeryd.concurrency = 2
75 #celeryd.log.file = celeryd.log
75 #celeryd.log.file = celeryd.log
76 celeryd.log.level = debug
76 celeryd.log.level = debug
77 celeryd.max.tasks.per.child = 1
77 celeryd.max.tasks.per.child = 1
78
78
79 #tasks will never be sent to the queue, but executed locally instead.
79 #tasks will never be sent to the queue, but executed locally instead.
80 celery.always.eager = false
80 celery.always.eager = false
81
81
82 ####################################
82 ####################################
83 ### BEAKER CACHE ####
83 ### BEAKER CACHE ####
84 ####################################
84 ####################################
85 beaker.cache.data_dir=/tmp/data/cache/data
85 beaker.cache.data_dir=/tmp/data/cache/data
86 beaker.cache.lock_dir=/tmp/data/cache/lock
86 beaker.cache.lock_dir=/tmp/data/cache/lock
87 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
87 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
88
88
89 beaker.cache.super_short_term.type=memory
89 beaker.cache.super_short_term.type=memory
90 beaker.cache.super_short_term.expire=10
90 beaker.cache.super_short_term.expire=10
91 beaker.cache.super_short_term.key_length = 256
91
92
92 beaker.cache.short_term.type=memory
93 beaker.cache.short_term.type=memory
93 beaker.cache.short_term.expire=60
94 beaker.cache.short_term.expire=60
95 beaker.cache.short_term.key_length = 256
94
96
95 beaker.cache.long_term.type=memory
97 beaker.cache.long_term.type=memory
96 beaker.cache.long_term.expire=36000
98 beaker.cache.long_term.expire=36000
99 beaker.cache.long_term.key_length = 256
97
100
98 beaker.cache.sql_cache_short.type=memory
101 beaker.cache.sql_cache_short.type=memory
99 beaker.cache.sql_cache_short.expire=10
102 beaker.cache.sql_cache_short.expire=10
103 beaker.cache.sql_cache_short.key_length = 256
100
104
101 beaker.cache.sql_cache_med.type=memory
105 beaker.cache.sql_cache_med.type=memory
102 beaker.cache.sql_cache_med.expire=360
106 beaker.cache.sql_cache_med.expire=360
107 beaker.cache.sql_cache_med.key_length = 256
103
108
104 beaker.cache.sql_cache_long.type=file
109 beaker.cache.sql_cache_long.type=file
105 beaker.cache.sql_cache_long.expire=3600
110 beaker.cache.sql_cache_long.expire=3600
111 beaker.cache.sql_cache_long.key_length = 256
106
112
107 ####################################
113 ####################################
108 ### BEAKER SESSION ####
114 ### BEAKER SESSION ####
109 ####################################
115 ####################################
110 ## Type of storage used for the session, current types are
116 ## Type of storage used for the session, current types are
111 ## dbm, file, memcached, database, and memory.
117 ## dbm, file, memcached, database, and memory.
112 ## The storage uses the Container API
118 ## The storage uses the Container API
113 ##that is also used by the cache system.
119 ##that is also used by the cache system.
114 beaker.session.type = file
120 beaker.session.type = file
115
121
116 beaker.session.key = rhodecode
122 beaker.session.key = rhodecode
117 beaker.session.secret = g654dcno0-9873jhgfreyu
123 beaker.session.secret = g654dcno0-9873jhgfreyu
118 beaker.session.timeout = 36000
124 beaker.session.timeout = 36000
119
125
120 ##auto save the session to not to use .save()
126 ##auto save the session to not to use .save()
121 beaker.session.auto = False
127 beaker.session.auto = False
122
128
123 ##true exire at browser close
129 ##true exire at browser close
124 #beaker.session.cookie_expires = 3600
130 #beaker.session.cookie_expires = 3600
125
131
126
132
127 ################################################################################
133 ################################################################################
128 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
134 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
129 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
135 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
130 ## execute malicious code after an exception is raised. ##
136 ## execute malicious code after an exception is raised. ##
131 ################################################################################
137 ################################################################################
132 #set debug = false
138 #set debug = false
133
139
134 ##################################
140 ##################################
135 ### LOGVIEW CONFIG ###
141 ### LOGVIEW CONFIG ###
136 ##################################
142 ##################################
137 logview.sqlalchemy = #faa
143 logview.sqlalchemy = #faa
138 logview.pylons.templating = #bfb
144 logview.pylons.templating = #bfb
139 logview.pylons.util = #eee
145 logview.pylons.util = #eee
140
146
141 #########################################################
147 #########################################################
142 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
148 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
143 #########################################################
149 #########################################################
144 sqlalchemy.db1.url = sqlite:///%(here)s/test.db
150 sqlalchemy.db1.url = sqlite:///%(here)s/test.db
145 #sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode_tests
151 #sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode_tests
146 #sqlalchemy.db1.echo = False
152 #sqlalchemy.db1.echo = false
147 #sqlalchemy.db1.pool_recycle = 3600
153 #sqlalchemy.db1.pool_recycle = 3600
148 sqlalchemy.convert_unicode = true
154 sqlalchemy.convert_unicode = true
149
155
150 ################################
156 ################################
151 ### LOGGING CONFIGURATION ####
157 ### LOGGING CONFIGURATION ####
152 ################################
158 ################################
153 [loggers]
159 [loggers]
154 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
160 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
155
161
156 [handlers]
162 [handlers]
157 keys = console
163 keys = console
158
164
159 [formatters]
165 [formatters]
160 keys = generic, color_formatter
166 keys = generic, color_formatter
161
167
162 #############
168 #############
163 ## LOGGERS ##
169 ## LOGGERS ##
164 #############
170 #############
165 [logger_root]
171 [logger_root]
166 level = ERROR
172 level = ERROR
167 handlers = console
173 handlers = console
168
174
169 [logger_routes]
175 [logger_routes]
170 level = ERROR
176 level = ERROR
171 handlers =
177 handlers =
172 qualname = routes.middleware
178 qualname = routes.middleware
173 # "level = DEBUG" logs the route matched and routing variables.
179 # "level = DEBUG" logs the route matched and routing variables.
174 propagate = 1
180 propagate = 1
175
181
176 [logger_beaker]
182 [logger_beaker]
177 level = DEBUG
183 level = DEBUG
178 handlers =
184 handlers =
179 qualname = beaker.container
185 qualname = beaker.container
180 propagate = 1
186 propagate = 1
181
187
182 [logger_templates]
188 [logger_templates]
183 level = INFO
189 level = INFO
184 handlers =
190 handlers =
185 qualname = pylons.templating
191 qualname = pylons.templating
186 propagate = 1
192 propagate = 1
187
193
188 [logger_rhodecode]
194 [logger_rhodecode]
189 level = ERROR
195 level = ERROR
190 handlers =
196 handlers =
191 qualname = rhodecode
197 qualname = rhodecode
192 propagate = 1
198 propagate = 1
193
199
194 [logger_sqlalchemy]
200 [logger_sqlalchemy]
195 level = ERROR
201 level = ERROR
196 handlers = console
202 handlers = console
197 qualname = sqlalchemy.engine
203 qualname = sqlalchemy.engine
198 propagate = 0
204 propagate = 0
199
205
200 ##############
206 ##############
201 ## HANDLERS ##
207 ## HANDLERS ##
202 ##############
208 ##############
203
209
204 [handler_console]
210 [handler_console]
205 class = StreamHandler
211 class = StreamHandler
206 args = (sys.stderr,)
212 args = (sys.stderr,)
207 level = NOTSET
213 level = NOTSET
208 formatter = generic
214 formatter = generic
209
215
210 ################
216 ################
211 ## FORMATTERS ##
217 ## FORMATTERS ##
212 ################
218 ################
213
219
214 [formatter_generic]
220 [formatter_generic]
215 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
221 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
216 datefmt = %Y-%m-%d %H:%M:%S
222 datefmt = %Y-%m-%d %H:%M:%S
217
223
218 [formatter_color_formatter]
224 [formatter_color_formatter]
219 class=rhodecode.lib.colored_formatter.ColorFormatter
225 class=rhodecode.lib.colored_formatter.ColorFormatter
220 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
226 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
221 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
227 datefmt = %Y-%m-%d %H:%M:%S
General Comments 0
You need to be logged in to leave comments. Login now