##// END OF EJS Templates
whitespace cleanup
marcink -
r2409:761e0038 beta
parent child Browse files
Show More
@@ -1,29 +1,29 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 import os
2 import os
3 import sys
3 import sys
4
4
5 try:
5 try:
6 import rhodecode
6 import rhodecode
7 from rhodecode.lib.hooks import handle_git_post_receive
7 from rhodecode.lib.hooks import handle_git_post_receive
8 except ImportError:
8 except ImportError:
9 rhodecode = None
9 rhodecode = None
10
10
11
11
12 def main():
12 def main():
13 if rhodecode is None:
13 if rhodecode is None:
14 # exit with success if we cannot import rhodecode !!
14 # exit with success if we cannot import rhodecode !!
15 # this allows simply push to this repo even without
15 # this allows simply push to this repo even without
16 # rhodecode
16 # rhodecode
17 sys.exit(0)
17 sys.exit(0)
18
18
19 repo_path = os.path.abspath('.')
19 repo_path = os.path.abspath('.')
20 push_data = sys.stdin.read().strip().split(' ')
20 push_data = sys.stdin.read().strip().split(' ')
21 # os.environ is modified here by a subprocess call that
21 # os.environ is modified here by a subprocess call that
22 # runs git and later git executes this hook.
22 # runs git and later git executes this hook.
23 # Environ get's some additional info from rhodecode system
23 # Environ get's some additional info from rhodecode system
24 # like IP or username from basic-auth
24 # like IP or username from basic-auth
25 handle_git_post_receive(repo_path, push_data, os.environ)
25 handle_git_post_receive(repo_path, push_data, os.environ)
26 sys.exit(0)
26 sys.exit(0)
27
27
28 if __name__ == '__main__':
28 if __name__ == '__main__':
29 main() No newline at end of file
29 main()
@@ -1,426 +1,426 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.settings
3 rhodecode.controllers.admin.settings
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 settings controller for rhodecode admin
6 settings controller for rhodecode admin
7
7
8 :created_on: Jul 14, 2010
8 :created_on: Jul 14, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 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 logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 import pkg_resources
29 import pkg_resources
30 import platform
30 import platform
31
31
32 from sqlalchemy import func
32 from sqlalchemy import func
33 from formencode import htmlfill
33 from formencode import htmlfill
34 from pylons import request, session, tmpl_context as c, url, config
34 from pylons import request, session, tmpl_context as c, url, config
35 from pylons.controllers.util import abort, redirect
35 from pylons.controllers.util import abort, redirect
36 from pylons.i18n.translation import _
36 from pylons.i18n.translation import _
37
37
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 HasPermissionAnyDecorator, NotAnonymous
40 HasPermissionAnyDecorator, NotAnonymous
41 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.celerylib import tasks, run_task
42 from rhodecode.lib.celerylib import tasks, run_task
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
44 set_rhodecode_config, repo_name_slug
44 set_rhodecode_config, repo_name_slug
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
46 RhodeCodeSetting
46 RhodeCodeSetting
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
48 ApplicationUiSettingsForm
48 ApplicationUiSettingsForm
49 from rhodecode.model.scm import ScmModel
49 from rhodecode.model.scm import ScmModel
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.db import User
51 from rhodecode.model.db import User
52 from rhodecode.model.notification import EmailNotificationModel
52 from rhodecode.model.notification import EmailNotificationModel
53 from rhodecode.model.meta import Session
53 from rhodecode.model.meta import Session
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class SettingsController(BaseController):
58 class SettingsController(BaseController):
59 """REST Controller styled on the Atom Publishing Protocol"""
59 """REST Controller styled on the Atom Publishing Protocol"""
60 # To properly map this controller, ensure your config/routing.py
60 # To properly map this controller, ensure your config/routing.py
61 # file has a resource setup:
61 # file has a resource setup:
62 # map.resource('setting', 'settings', controller='admin/settings',
62 # map.resource('setting', 'settings', controller='admin/settings',
63 # path_prefix='/admin', name_prefix='admin_')
63 # path_prefix='/admin', name_prefix='admin_')
64
64
65 @LoginRequired()
65 @LoginRequired()
66 def __before__(self):
66 def __before__(self):
67 c.admin_user = session.get('admin_user')
67 c.admin_user = session.get('admin_user')
68 c.admin_username = session.get('admin_username')
68 c.admin_username = session.get('admin_username')
69 c.modules = sorted([(p.project_name, p.version)
69 c.modules = sorted([(p.project_name, p.version)
70 for p in pkg_resources.working_set],
70 for p in pkg_resources.working_set],
71 key=lambda k: k[0].lower())
71 key=lambda k: k[0].lower())
72 c.py_version = platform.python_version()
72 c.py_version = platform.python_version()
73 c.platform = platform.platform()
73 c.platform = platform.platform()
74 super(SettingsController, self).__before__()
74 super(SettingsController, self).__before__()
75
75
76 @HasPermissionAllDecorator('hg.admin')
76 @HasPermissionAllDecorator('hg.admin')
77 def index(self, format='html'):
77 def index(self, format='html'):
78 """GET /admin/settings: All items in the collection"""
78 """GET /admin/settings: All items in the collection"""
79 # url('admin_settings')
79 # url('admin_settings')
80
80
81 defaults = RhodeCodeSetting.get_app_settings()
81 defaults = RhodeCodeSetting.get_app_settings()
82 defaults.update(self.get_hg_ui_settings())
82 defaults.update(self.get_hg_ui_settings())
83
83
84 return htmlfill.render(
84 return htmlfill.render(
85 render('admin/settings/settings.html'),
85 render('admin/settings/settings.html'),
86 defaults=defaults,
86 defaults=defaults,
87 encoding="UTF-8",
87 encoding="UTF-8",
88 force_defaults=False
88 force_defaults=False
89 )
89 )
90
90
91 @HasPermissionAllDecorator('hg.admin')
91 @HasPermissionAllDecorator('hg.admin')
92 def create(self):
92 def create(self):
93 """POST /admin/settings: Create a new item"""
93 """POST /admin/settings: Create a new item"""
94 # url('admin_settings')
94 # url('admin_settings')
95
95
96 @HasPermissionAllDecorator('hg.admin')
96 @HasPermissionAllDecorator('hg.admin')
97 def new(self, format='html'):
97 def new(self, format='html'):
98 """GET /admin/settings/new: Form to create a new item"""
98 """GET /admin/settings/new: Form to create a new item"""
99 # url('admin_new_setting')
99 # url('admin_new_setting')
100
100
101 @HasPermissionAllDecorator('hg.admin')
101 @HasPermissionAllDecorator('hg.admin')
102 def update(self, setting_id):
102 def update(self, setting_id):
103 """PUT /admin/settings/setting_id: Update an existing item"""
103 """PUT /admin/settings/setting_id: Update an existing item"""
104 # Forms posted to this method should contain a hidden field:
104 # Forms posted to this method should contain a hidden field:
105 # <input type="hidden" name="_method" value="PUT" />
105 # <input type="hidden" name="_method" value="PUT" />
106 # Or using helpers:
106 # Or using helpers:
107 # h.form(url('admin_setting', setting_id=ID),
107 # h.form(url('admin_setting', setting_id=ID),
108 # method='put')
108 # method='put')
109 # url('admin_setting', setting_id=ID)
109 # url('admin_setting', setting_id=ID)
110 if setting_id == 'mapping':
110 if setting_id == 'mapping':
111 rm_obsolete = request.POST.get('destroy', False)
111 rm_obsolete = request.POST.get('destroy', False)
112 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
112 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
113 initial = ScmModel().repo_scan()
113 initial = ScmModel().repo_scan()
114 log.debug('invalidating all repositories')
114 log.debug('invalidating all repositories')
115 for repo_name in initial.keys():
115 for repo_name in initial.keys():
116 invalidate_cache('get_repo_cached_%s' % repo_name)
116 invalidate_cache('get_repo_cached_%s' % repo_name)
117
117
118 added, removed = repo2db_mapper(initial, rm_obsolete)
118 added, removed = repo2db_mapper(initial, rm_obsolete)
119
119
120 h.flash(_('Repositories successfully'
120 h.flash(_('Repositories successfully'
121 ' rescanned added: %s,removed: %s') % (added, removed),
121 ' rescanned added: %s,removed: %s') % (added, removed),
122 category='success')
122 category='success')
123
123
124 if setting_id == 'whoosh':
124 if setting_id == 'whoosh':
125 repo_location = self.get_hg_ui_settings()['paths_root_path']
125 repo_location = self.get_hg_ui_settings()['paths_root_path']
126 full_index = request.POST.get('full_index', False)
126 full_index = request.POST.get('full_index', False)
127 run_task(tasks.whoosh_index, repo_location, full_index)
127 run_task(tasks.whoosh_index, repo_location, full_index)
128
128
129 h.flash(_('Whoosh reindex task scheduled'), category='success')
129 h.flash(_('Whoosh reindex task scheduled'), category='success')
130 if setting_id == 'global':
130 if setting_id == 'global':
131
131
132 application_form = ApplicationSettingsForm()()
132 application_form = ApplicationSettingsForm()()
133 try:
133 try:
134 form_result = application_form.to_python(dict(request.POST))
134 form_result = application_form.to_python(dict(request.POST))
135
135
136 try:
136 try:
137 hgsettings1 = RhodeCodeSetting.get_by_name('title')
137 hgsettings1 = RhodeCodeSetting.get_by_name('title')
138 hgsettings1.app_settings_value = \
138 hgsettings1.app_settings_value = \
139 form_result['rhodecode_title']
139 form_result['rhodecode_title']
140
140
141 hgsettings2 = RhodeCodeSetting.get_by_name('realm')
141 hgsettings2 = RhodeCodeSetting.get_by_name('realm')
142 hgsettings2.app_settings_value = \
142 hgsettings2.app_settings_value = \
143 form_result['rhodecode_realm']
143 form_result['rhodecode_realm']
144
144
145 hgsettings3 = RhodeCodeSetting.get_by_name('ga_code')
145 hgsettings3 = RhodeCodeSetting.get_by_name('ga_code')
146 hgsettings3.app_settings_value = \
146 hgsettings3.app_settings_value = \
147 form_result['rhodecode_ga_code']
147 form_result['rhodecode_ga_code']
148
148
149 self.sa.add(hgsettings1)
149 self.sa.add(hgsettings1)
150 self.sa.add(hgsettings2)
150 self.sa.add(hgsettings2)
151 self.sa.add(hgsettings3)
151 self.sa.add(hgsettings3)
152 self.sa.commit()
152 self.sa.commit()
153 set_rhodecode_config(config)
153 set_rhodecode_config(config)
154 h.flash(_('Updated application settings'),
154 h.flash(_('Updated application settings'),
155 category='success')
155 category='success')
156
156
157 except Exception:
157 except Exception:
158 log.error(traceback.format_exc())
158 log.error(traceback.format_exc())
159 h.flash(_('error occurred during updating '
159 h.flash(_('error occurred during updating '
160 'application settings'),
160 'application settings'),
161 category='error')
161 category='error')
162
162
163 self.sa.rollback()
163 self.sa.rollback()
164
164
165 except formencode.Invalid, errors:
165 except formencode.Invalid, errors:
166 return htmlfill.render(
166 return htmlfill.render(
167 render('admin/settings/settings.html'),
167 render('admin/settings/settings.html'),
168 defaults=errors.value,
168 defaults=errors.value,
169 errors=errors.error_dict or {},
169 errors=errors.error_dict or {},
170 prefix_error=False,
170 prefix_error=False,
171 encoding="UTF-8")
171 encoding="UTF-8")
172
172
173 if setting_id == 'mercurial':
173 if setting_id == 'mercurial':
174 application_form = ApplicationUiSettingsForm()()
174 application_form = ApplicationUiSettingsForm()()
175 try:
175 try:
176 form_result = application_form.to_python(dict(request.POST))
176 form_result = application_form.to_python(dict(request.POST))
177 # fix namespaces for hooks
177 # fix namespaces for hooks
178 _f = lambda s: s.replace('.', '_')
178 _f = lambda s: s.replace('.', '_')
179 try:
179 try:
180
180
181 hgsettings1 = self.sa.query(RhodeCodeUi)\
181 hgsettings1 = self.sa.query(RhodeCodeUi)\
182 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
182 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
183 hgsettings1.ui_value = form_result['web_push_ssl']
183 hgsettings1.ui_value = form_result['web_push_ssl']
184
184
185 hgsettings2 = self.sa.query(RhodeCodeUi)\
185 hgsettings2 = self.sa.query(RhodeCodeUi)\
186 .filter(RhodeCodeUi.ui_key == '/').one()
186 .filter(RhodeCodeUi.ui_key == '/').one()
187 hgsettings2.ui_value = form_result['paths_root_path']
187 hgsettings2.ui_value = form_result['paths_root_path']
188
188
189 #HOOKS
189 #HOOKS
190 hgsettings3 = self.sa.query(RhodeCodeUi)\
190 hgsettings3 = self.sa.query(RhodeCodeUi)\
191 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_UPDATE)\
191 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_UPDATE)\
192 .one()
192 .one()
193 hgsettings3.ui_active = bool(form_result[_f('hooks_%s' %
193 hgsettings3.ui_active = bool(form_result[_f('hooks_%s' %
194 RhodeCodeUi.HOOK_UPDATE)])
194 RhodeCodeUi.HOOK_UPDATE)])
195
195
196 hgsettings4 = self.sa.query(RhodeCodeUi)\
196 hgsettings4 = self.sa.query(RhodeCodeUi)\
197 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_REPO_SIZE)\
197 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_REPO_SIZE)\
198 .one()
198 .one()
199 hgsettings4.ui_active = bool(form_result[_f('hooks_%s' %
199 hgsettings4.ui_active = bool(form_result[_f('hooks_%s' %
200 RhodeCodeUi.HOOK_REPO_SIZE)])
200 RhodeCodeUi.HOOK_REPO_SIZE)])
201
201
202 hgsettings5 = self.sa.query(RhodeCodeUi)\
202 hgsettings5 = self.sa.query(RhodeCodeUi)\
203 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_PUSH)\
203 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_PUSH)\
204 .one()
204 .one()
205 hgsettings5.ui_active = bool(form_result[_f('hooks_%s' %
205 hgsettings5.ui_active = bool(form_result[_f('hooks_%s' %
206 RhodeCodeUi.HOOK_PUSH)])
206 RhodeCodeUi.HOOK_PUSH)])
207
207
208 hgsettings6 = self.sa.query(RhodeCodeUi)\
208 hgsettings6 = self.sa.query(RhodeCodeUi)\
209 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_PULL)\
209 .filter(RhodeCodeUi.ui_key == RhodeCodeUi.HOOK_PULL)\
210 .one()
210 .one()
211 hgsettings6.ui_active = bool(form_result[_f('hooks_%s' %
211 hgsettings6.ui_active = bool(form_result[_f('hooks_%s' %
212 RhodeCodeUi.HOOK_PULL)])
212 RhodeCodeUi.HOOK_PULL)])
213
213
214 self.sa.add(hgsettings1)
214 self.sa.add(hgsettings1)
215 self.sa.add(hgsettings2)
215 self.sa.add(hgsettings2)
216 self.sa.add(hgsettings3)
216 self.sa.add(hgsettings3)
217 self.sa.add(hgsettings4)
217 self.sa.add(hgsettings4)
218 self.sa.add(hgsettings5)
218 self.sa.add(hgsettings5)
219 self.sa.add(hgsettings6)
219 self.sa.add(hgsettings6)
220 self.sa.commit()
220 self.sa.commit()
221
221
222 h.flash(_('Updated mercurial settings'),
222 h.flash(_('Updated mercurial settings'),
223 category='success')
223 category='success')
224
224
225 except:
225 except:
226 log.error(traceback.format_exc())
226 log.error(traceback.format_exc())
227 h.flash(_('error occurred during updating '
227 h.flash(_('error occurred during updating '
228 'application settings'), category='error')
228 'application settings'), category='error')
229
229
230 self.sa.rollback()
230 self.sa.rollback()
231
231
232 except formencode.Invalid, errors:
232 except formencode.Invalid, errors:
233 return htmlfill.render(
233 return htmlfill.render(
234 render('admin/settings/settings.html'),
234 render('admin/settings/settings.html'),
235 defaults=errors.value,
235 defaults=errors.value,
236 errors=errors.error_dict or {},
236 errors=errors.error_dict or {},
237 prefix_error=False,
237 prefix_error=False,
238 encoding="UTF-8")
238 encoding="UTF-8")
239
239
240 if setting_id == 'hooks':
240 if setting_id == 'hooks':
241 ui_key = request.POST.get('new_hook_ui_key')
241 ui_key = request.POST.get('new_hook_ui_key')
242 ui_value = request.POST.get('new_hook_ui_value')
242 ui_value = request.POST.get('new_hook_ui_value')
243 try:
243 try:
244
244
245 if ui_value and ui_key:
245 if ui_value and ui_key:
246 RhodeCodeUi.create_or_update_hook(ui_key, ui_value)
246 RhodeCodeUi.create_or_update_hook(ui_key, ui_value)
247 h.flash(_('Added new hook'),
247 h.flash(_('Added new hook'),
248 category='success')
248 category='success')
249
249
250 # check for edits
250 # check for edits
251 update = False
251 update = False
252 _d = request.POST.dict_of_lists()
252 _d = request.POST.dict_of_lists()
253 for k, v in zip(_d.get('hook_ui_key', []),
253 for k, v in zip(_d.get('hook_ui_key', []),
254 _d.get('hook_ui_value_new', [])):
254 _d.get('hook_ui_value_new', [])):
255 RhodeCodeUi.create_or_update_hook(k, v)
255 RhodeCodeUi.create_or_update_hook(k, v)
256 update = True
256 update = True
257
257
258 if update:
258 if update:
259 h.flash(_('Updated hooks'), category='success')
259 h.flash(_('Updated hooks'), category='success')
260 self.sa.commit()
260 self.sa.commit()
261 except:
261 except:
262 log.error(traceback.format_exc())
262 log.error(traceback.format_exc())
263 h.flash(_('error occurred during hook creation'),
263 h.flash(_('error occurred during hook creation'),
264 category='error')
264 category='error')
265
265
266 return redirect(url('admin_edit_setting', setting_id='hooks'))
266 return redirect(url('admin_edit_setting', setting_id='hooks'))
267
267
268 if setting_id == 'email':
268 if setting_id == 'email':
269 test_email = request.POST.get('test_email')
269 test_email = request.POST.get('test_email')
270 test_email_subj = 'RhodeCode TestEmail'
270 test_email_subj = 'RhodeCode TestEmail'
271 test_email_body = 'RhodeCode Email test'
271 test_email_body = 'RhodeCode Email test'
272
272
273 test_email_html_body = EmailNotificationModel()\
273 test_email_html_body = EmailNotificationModel()\
274 .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT,
274 .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT,
275 body=test_email_body)
275 body=test_email_body)
276
276
277 recipients = [test_email] if [test_email] else None
277 recipients = [test_email] if [test_email] else None
278
278
279 run_task(tasks.send_email, recipients, test_email_subj,
279 run_task(tasks.send_email, recipients, test_email_subj,
280 test_email_body, test_email_html_body)
280 test_email_body, test_email_html_body)
281
281
282 h.flash(_('Email task created'), category='success')
282 h.flash(_('Email task created'), category='success')
283 return redirect(url('admin_settings'))
283 return redirect(url('admin_settings'))
284
284
285 @HasPermissionAllDecorator('hg.admin')
285 @HasPermissionAllDecorator('hg.admin')
286 def delete(self, setting_id):
286 def delete(self, setting_id):
287 """DELETE /admin/settings/setting_id: Delete an existing item"""
287 """DELETE /admin/settings/setting_id: Delete an existing item"""
288 # Forms posted to this method should contain a hidden field:
288 # Forms posted to this method should contain a hidden field:
289 # <input type="hidden" name="_method" value="DELETE" />
289 # <input type="hidden" name="_method" value="DELETE" />
290 # Or using helpers:
290 # Or using helpers:
291 # h.form(url('admin_setting', setting_id=ID),
291 # h.form(url('admin_setting', setting_id=ID),
292 # method='delete')
292 # method='delete')
293 # url('admin_setting', setting_id=ID)
293 # url('admin_setting', setting_id=ID)
294 if setting_id == 'hooks':
294 if setting_id == 'hooks':
295 hook_id = request.POST.get('hook_id')
295 hook_id = request.POST.get('hook_id')
296 RhodeCodeUi.delete(hook_id)
296 RhodeCodeUi.delete(hook_id)
297 self.sa.commit()
297 self.sa.commit()
298
298
299 @HasPermissionAllDecorator('hg.admin')
299 @HasPermissionAllDecorator('hg.admin')
300 def show(self, setting_id, format='html'):
300 def show(self, setting_id, format='html'):
301 """
301 """
302 GET /admin/settings/setting_id: Show a specific item"""
302 GET /admin/settings/setting_id: Show a specific item"""
303 # url('admin_setting', setting_id=ID)
303 # url('admin_setting', setting_id=ID)
304
304
305 @HasPermissionAllDecorator('hg.admin')
305 @HasPermissionAllDecorator('hg.admin')
306 def edit(self, setting_id, format='html'):
306 def edit(self, setting_id, format='html'):
307 """
307 """
308 GET /admin/settings/setting_id/edit: Form to
308 GET /admin/settings/setting_id/edit: Form to
309 edit an existing item"""
309 edit an existing item"""
310 # url('admin_edit_setting', setting_id=ID)
310 # url('admin_edit_setting', setting_id=ID)
311
311
312 c.hooks = RhodeCodeUi.get_builtin_hooks()
312 c.hooks = RhodeCodeUi.get_builtin_hooks()
313 c.custom_hooks = RhodeCodeUi.get_custom_hooks()
313 c.custom_hooks = RhodeCodeUi.get_custom_hooks()
314
314
315 return htmlfill.render(
315 return htmlfill.render(
316 render('admin/settings/hooks.html'),
316 render('admin/settings/hooks.html'),
317 defaults={},
317 defaults={},
318 encoding="UTF-8",
318 encoding="UTF-8",
319 force_defaults=False
319 force_defaults=False
320 )
320 )
321
321
322 @NotAnonymous()
322 @NotAnonymous()
323 def my_account(self):
323 def my_account(self):
324 """
324 """
325 GET /_admin/my_account Displays info about my account
325 GET /_admin/my_account Displays info about my account
326 """
326 """
327 # url('admin_settings_my_account')
327 # url('admin_settings_my_account')
328
328
329 c.user = User.get(self.rhodecode_user.user_id)
329 c.user = User.get(self.rhodecode_user.user_id)
330 all_repos = self.sa.query(Repository)\
330 all_repos = self.sa.query(Repository)\
331 .filter(Repository.user_id == c.user.user_id)\
331 .filter(Repository.user_id == c.user.user_id)\
332 .order_by(func.lower(Repository.repo_name)).all()
332 .order_by(func.lower(Repository.repo_name)).all()
333
333
334 c.user_repos = ScmModel().get_repos(all_repos)
334 c.user_repos = ScmModel().get_repos(all_repos)
335
335
336 if c.user.username == 'default':
336 if c.user.username == 'default':
337 h.flash(_("You can't edit this user since it's"
337 h.flash(_("You can't edit this user since it's"
338 " crucial for entire application"), category='warning')
338 " crucial for entire application"), category='warning')
339 return redirect(url('users'))
339 return redirect(url('users'))
340
340
341 defaults = c.user.get_dict()
341 defaults = c.user.get_dict()
342
342
343 c.form = htmlfill.render(
343 c.form = htmlfill.render(
344 render('admin/users/user_edit_my_account_form.html'),
344 render('admin/users/user_edit_my_account_form.html'),
345 defaults=defaults,
345 defaults=defaults,
346 encoding="UTF-8",
346 encoding="UTF-8",
347 force_defaults=False
347 force_defaults=False
348 )
348 )
349 return render('admin/users/user_edit_my_account.html')
349 return render('admin/users/user_edit_my_account.html')
350
350
351 def my_account_update(self):
351 def my_account_update(self):
352 """PUT /_admin/my_account_update: Update an existing item"""
352 """PUT /_admin/my_account_update: Update an existing item"""
353 # Forms posted to this method should contain a hidden field:
353 # Forms posted to this method should contain a hidden field:
354 # <input type="hidden" name="_method" value="PUT" />
354 # <input type="hidden" name="_method" value="PUT" />
355 # Or using helpers:
355 # Or using helpers:
356 # h.form(url('admin_settings_my_account_update'),
356 # h.form(url('admin_settings_my_account_update'),
357 # method='put')
357 # method='put')
358 # url('admin_settings_my_account_update', id=ID)
358 # url('admin_settings_my_account_update', id=ID)
359 user_model = UserModel()
359 user_model = UserModel()
360 uid = self.rhodecode_user.user_id
360 uid = self.rhodecode_user.user_id
361 _form = UserForm(edit=True,
361 _form = UserForm(edit=True,
362 old_data={'user_id': uid,
362 old_data={'user_id': uid,
363 'email': self.rhodecode_user.email})()
363 'email': self.rhodecode_user.email})()
364 form_result = {}
364 form_result = {}
365 try:
365 try:
366 form_result = _form.to_python(dict(request.POST))
366 form_result = _form.to_python(dict(request.POST))
367 user_model.update_my_account(uid, form_result)
367 user_model.update_my_account(uid, form_result)
368 h.flash(_('Your account was updated successfully'),
368 h.flash(_('Your account was updated successfully'),
369 category='success')
369 category='success')
370 Session.commit()
370 Session.commit()
371 except formencode.Invalid, errors:
371 except formencode.Invalid, errors:
372 c.user = User.get(self.rhodecode_user.user_id)
372 c.user = User.get(self.rhodecode_user.user_id)
373 all_repos = self.sa.query(Repository)\
373 all_repos = self.sa.query(Repository)\
374 .filter(Repository.user_id == c.user.user_id)\
374 .filter(Repository.user_id == c.user.user_id)\
375 .order_by(func.lower(Repository.repo_name))\
375 .order_by(func.lower(Repository.repo_name))\
376 .all()
376 .all()
377 c.user_repos = ScmModel().get_repos(all_repos)
377 c.user_repos = ScmModel().get_repos(all_repos)
378
378
379 c.form = htmlfill.render(
379 c.form = htmlfill.render(
380 render('admin/users/user_edit_my_account_form.html'),
380 render('admin/users/user_edit_my_account_form.html'),
381 defaults=errors.value,
381 defaults=errors.value,
382 errors=errors.error_dict or {},
382 errors=errors.error_dict or {},
383 prefix_error=False,
383 prefix_error=False,
384 encoding="UTF-8")
384 encoding="UTF-8")
385 return render('admin/users/user_edit_my_account.html')
385 return render('admin/users/user_edit_my_account.html')
386 except Exception:
386 except Exception:
387 log.error(traceback.format_exc())
387 log.error(traceback.format_exc())
388 h.flash(_('error occurred during update of user %s') \
388 h.flash(_('error occurred during update of user %s') \
389 % form_result.get('username'), category='error')
389 % form_result.get('username'), category='error')
390
390
391 return redirect(url('my_account'))
391 return redirect(url('my_account'))
392
392
393 @NotAnonymous()
393 @NotAnonymous()
394 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
394 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
395 def create_repository(self):
395 def create_repository(self):
396 """GET /_admin/create_repository: Form to create a new item"""
396 """GET /_admin/create_repository: Form to create a new item"""
397
397
398 c.repo_groups = RepoGroup.groups_choices()
398 c.repo_groups = RepoGroup.groups_choices()
399 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
399 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
400
400
401 new_repo = request.GET.get('repo', '')
401 new_repo = request.GET.get('repo', '')
402 c.new_repo = repo_name_slug(new_repo)
402 c.new_repo = repo_name_slug(new_repo)
403
403
404 return render('admin/repos/repo_add_create_repository.html')
404 return render('admin/repos/repo_add_create_repository.html')
405
405
406 def get_hg_ui_settings(self):
406 def get_hg_ui_settings(self):
407 ret = self.sa.query(RhodeCodeUi).all()
407 ret = self.sa.query(RhodeCodeUi).all()
408
408
409 if not ret:
409 if not ret:
410 raise Exception('Could not get application ui settings !')
410 raise Exception('Could not get application ui settings !')
411 settings = {}
411 settings = {}
412 for each in ret:
412 for each in ret:
413 k = each.ui_key
413 k = each.ui_key
414 v = each.ui_value
414 v = each.ui_value
415 if k == '/':
415 if k == '/':
416 k = 'root_path'
416 k = 'root_path'
417
417
418 if k.find('.') != -1:
418 if k.find('.') != -1:
419 k = k.replace('.', '_')
419 k = k.replace('.', '_')
420
420
421 if each.ui_section == 'hooks':
421 if each.ui_section == 'hooks':
422 v = each.ui_active
422 v = each.ui_active
423
423
424 settings[each.ui_section + '_' + k] = v
424 settings[each.ui_section + '_' + k] = v
425
425
426 return settings
426 return settings
@@ -1,261 +1,260 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.hooks
3 rhodecode.lib.hooks
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Hooks runned by rhodecode
6 Hooks runned by rhodecode
7
7
8 :created_on: Aug 6, 2010
8 :created_on: Aug 6, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 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 sys
26 import sys
27 import binascii
27 import binascii
28 from inspect import isfunction
28 from inspect import isfunction
29
29
30 from mercurial.scmutil import revrange
30 from mercurial.scmutil import revrange
31 from mercurial.node import nullrev
31 from mercurial.node import nullrev
32
32
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.lib.utils import action_logger
34 from rhodecode.lib.utils import action_logger
35 from rhodecode.lib.vcs.backends.base import EmptyChangeset
35 from rhodecode.lib.vcs.backends.base import EmptyChangeset
36
36
37
37
38 def _get_scm_size(alias, root_path):
38 def _get_scm_size(alias, root_path):
39
39
40 if not alias.startswith('.'):
40 if not alias.startswith('.'):
41 alias += '.'
41 alias += '.'
42
42
43 size_scm, size_root = 0, 0
43 size_scm, size_root = 0, 0
44 for path, dirs, files in os.walk(root_path):
44 for path, dirs, files in os.walk(root_path):
45 if path.find(alias) != -1:
45 if path.find(alias) != -1:
46 for f in files:
46 for f in files:
47 try:
47 try:
48 size_scm += os.path.getsize(os.path.join(path, f))
48 size_scm += os.path.getsize(os.path.join(path, f))
49 except OSError:
49 except OSError:
50 pass
50 pass
51 else:
51 else:
52 for f in files:
52 for f in files:
53 try:
53 try:
54 size_root += os.path.getsize(os.path.join(path, f))
54 size_root += os.path.getsize(os.path.join(path, f))
55 except OSError:
55 except OSError:
56 pass
56 pass
57
57
58 size_scm_f = h.format_byte_size(size_scm)
58 size_scm_f = h.format_byte_size(size_scm)
59 size_root_f = h.format_byte_size(size_root)
59 size_root_f = h.format_byte_size(size_root)
60 size_total_f = h.format_byte_size(size_root + size_scm)
60 size_total_f = h.format_byte_size(size_root + size_scm)
61
61
62 return size_scm_f, size_root_f, size_total_f
62 return size_scm_f, size_root_f, size_total_f
63
63
64
64
65 def repo_size(ui, repo, hooktype=None, **kwargs):
65 def repo_size(ui, repo, hooktype=None, **kwargs):
66 """
66 """
67 Presents size of repository after push
67 Presents size of repository after push
68
68
69 :param ui:
69 :param ui:
70 :param repo:
70 :param repo:
71 :param hooktype:
71 :param hooktype:
72 """
72 """
73
73
74 size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root)
74 size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root)
75
75
76 last_cs = repo[len(repo) - 1]
76 last_cs = repo[len(repo) - 1]
77
77
78 msg = ('Repository size .hg:%s repo:%s total:%s\n'
78 msg = ('Repository size .hg:%s repo:%s total:%s\n'
79 'Last revision is now r%s:%s\n') % (
79 'Last revision is now r%s:%s\n') % (
80 size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
80 size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
81 )
81 )
82
82
83 sys.stdout.write(msg)
83 sys.stdout.write(msg)
84
84
85
85
86 def log_pull_action(ui, repo, **kwargs):
86 def log_pull_action(ui, repo, **kwargs):
87 """
87 """
88 Logs user last pull action
88 Logs user last pull action
89
89
90 :param ui:
90 :param ui:
91 :param repo:
91 :param repo:
92 """
92 """
93
93
94 extras = dict(repo.ui.configitems('rhodecode_extras'))
94 extras = dict(repo.ui.configitems('rhodecode_extras'))
95 username = extras['username']
95 username = extras['username']
96 repository = extras['repository']
96 repository = extras['repository']
97 scm = extras['scm']
97 scm = extras['scm']
98 action = 'pull'
98 action = 'pull'
99
99
100 action_logger(username, action, repository, extras['ip'], commit=True)
100 action_logger(username, action, repository, extras['ip'], commit=True)
101 # extension hook call
101 # extension hook call
102 from rhodecode import EXTENSIONS
102 from rhodecode import EXTENSIONS
103 callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
103 callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
104
104
105 if isfunction(callback):
105 if isfunction(callback):
106 kw = {}
106 kw = {}
107 kw.update(extras)
107 kw.update(extras)
108 callback(**kw)
108 callback(**kw)
109 return 0
109 return 0
110
110
111
111
112 def log_push_action(ui, repo, **kwargs):
112 def log_push_action(ui, repo, **kwargs):
113 """
113 """
114 Maps user last push action to new changeset id, from mercurial
114 Maps user last push action to new changeset id, from mercurial
115
115
116 :param ui:
116 :param ui:
117 :param repo: repo object containing the `ui` object
117 :param repo: repo object containing the `ui` object
118 """
118 """
119
119
120 extras = dict(repo.ui.configitems('rhodecode_extras'))
120 extras = dict(repo.ui.configitems('rhodecode_extras'))
121 username = extras['username']
121 username = extras['username']
122 repository = extras['repository']
122 repository = extras['repository']
123 action = extras['action'] + ':%s'
123 action = extras['action'] + ':%s'
124 scm = extras['scm']
124 scm = extras['scm']
125
125
126 if scm == 'hg':
126 if scm == 'hg':
127 node = kwargs['node']
127 node = kwargs['node']
128
128
129 def get_revs(repo, rev_opt):
129 def get_revs(repo, rev_opt):
130 if rev_opt:
130 if rev_opt:
131 revs = revrange(repo, rev_opt)
131 revs = revrange(repo, rev_opt)
132
132
133 if len(revs) == 0:
133 if len(revs) == 0:
134 return (nullrev, nullrev)
134 return (nullrev, nullrev)
135 return (max(revs), min(revs))
135 return (max(revs), min(revs))
136 else:
136 else:
137 return (len(repo) - 1, 0)
137 return (len(repo) - 1, 0)
138
138
139 stop, start = get_revs(repo, [node + ':'])
139 stop, start = get_revs(repo, [node + ':'])
140 h = binascii.hexlify
140 h = binascii.hexlify
141 revs = [h(repo[r].node()) for r in xrange(start, stop + 1)]
141 revs = [h(repo[r].node()) for r in xrange(start, stop + 1)]
142 elif scm == 'git':
142 elif scm == 'git':
143 revs = kwargs.get('_git_revs', [])
143 revs = kwargs.get('_git_revs', [])
144 if '_git_revs' in kwargs:
144 if '_git_revs' in kwargs:
145 kwargs.pop('_git_revs')
145 kwargs.pop('_git_revs')
146
146
147 action = action % ','.join(revs)
147 action = action % ','.join(revs)
148
148
149 action_logger(username, action, repository, extras['ip'], commit=True)
149 action_logger(username, action, repository, extras['ip'], commit=True)
150
150
151 # extension hook call
151 # extension hook call
152 from rhodecode import EXTENSIONS
152 from rhodecode import EXTENSIONS
153 callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
153 callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
154 if isfunction(callback):
154 if isfunction(callback):
155 kw = {'pushed_revs': revs}
155 kw = {'pushed_revs': revs}
156 kw.update(extras)
156 kw.update(extras)
157 callback(**kw)
157 callback(**kw)
158 return 0
158 return 0
159
159
160
160
161 def log_create_repository(repository_dict, created_by, **kwargs):
161 def log_create_repository(repository_dict, created_by, **kwargs):
162 """
162 """
163 Post create repository Hook. This is a dummy function for admins to re-use
163 Post create repository Hook. This is a dummy function for admins to re-use
164 if needed. It's taken from rhodecode-extensions module and executed
164 if needed. It's taken from rhodecode-extensions module and executed
165 if present
165 if present
166
166
167 :param repository: dict dump of repository object
167 :param repository: dict dump of repository object
168 :param created_by: username who created repository
168 :param created_by: username who created repository
169 :param created_date: date of creation
169 :param created_date: date of creation
170
170
171 available keys of repository_dict:
171 available keys of repository_dict:
172
172
173 'repo_type',
173 'repo_type',
174 'description',
174 'description',
175 'private',
175 'private',
176 'created_on',
176 'created_on',
177 'enable_downloads',
177 'enable_downloads',
178 'repo_id',
178 'repo_id',
179 'user_id',
179 'user_id',
180 'enable_statistics',
180 'enable_statistics',
181 'clone_uri',
181 'clone_uri',
182 'fork_id',
182 'fork_id',
183 'group_id',
183 'group_id',
184 'repo_name'
184 'repo_name'
185
185
186 """
186 """
187 from rhodecode import EXTENSIONS
187 from rhodecode import EXTENSIONS
188 callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
188 callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
189 if isfunction(callback):
189 if isfunction(callback):
190 kw = {}
190 kw = {}
191 kw.update(repository_dict)
191 kw.update(repository_dict)
192 kw.update({'created_by': created_by})
192 kw.update({'created_by': created_by})
193 kw.update(kwargs)
193 kw.update(kwargs)
194 return callback(**kw)
194 return callback(**kw)
195
195
196 return 0
196 return 0
197
197
198
198
199 def handle_git_post_receive(repo_path, revs, env):
199 def handle_git_post_receive(repo_path, revs, env):
200 """
200 """
201 A really hacky method that is runned by git post-receive hook and logs
201 A really hacky method that is runned by git post-receive hook and logs
202 an push action together with pushed revisions. It's runned by subprocess
202 an push action together with pushed revisions. It's executed by subprocess
203 thus needs all info to be able to create a temp pylons enviroment, connect
203 thus needs all info to be able to create a on the fly pylons enviroment,
204 to database and run the logging code. Hacky as sh**t but works. ps.
204 connect to database and run the logging code. Hacky as sh*t but works.
205 GIT SUCKS
206
205
207 :param repo_path:
206 :param repo_path:
208 :type repo_path:
207 :type repo_path:
209 :param revs:
208 :param revs:
210 :type revs:
209 :type revs:
211 :param env:
210 :param env:
212 :type env:
211 :type env:
213 """
212 """
214 from paste.deploy import appconfig
213 from paste.deploy import appconfig
215 from sqlalchemy import engine_from_config
214 from sqlalchemy import engine_from_config
216 from rhodecode.config.environment import load_environment
215 from rhodecode.config.environment import load_environment
217 from rhodecode.model import init_model
216 from rhodecode.model import init_model
218 from rhodecode.model.db import RhodeCodeUi
217 from rhodecode.model.db import RhodeCodeUi
219 from rhodecode.lib.utils import make_ui
218 from rhodecode.lib.utils import make_ui
220 from rhodecode.model.db import Repository
219 from rhodecode.model.db import Repository
221
220
222 path, ini_name = os.path.split(env['RHODECODE_CONFIG_FILE'])
221 path, ini_name = os.path.split(env['RHODECODE_CONFIG_FILE'])
223 conf = appconfig('config:%s' % ini_name, relative_to=path)
222 conf = appconfig('config:%s' % ini_name, relative_to=path)
224 load_environment(conf.global_conf, conf.local_conf)
223 load_environment(conf.global_conf, conf.local_conf)
225
224
226 engine = engine_from_config(conf, 'sqlalchemy.db1.')
225 engine = engine_from_config(conf, 'sqlalchemy.db1.')
227 init_model(engine)
226 init_model(engine)
228
227
229 baseui = make_ui('db')
228 baseui = make_ui('db')
230 repo = Repository.get_by_full_path(repo_path)
229 repo = Repository.get_by_full_path(repo_path)
231
230
232 _hooks = dict(baseui.configitems('hooks')) or {}
231 _hooks = dict(baseui.configitems('hooks')) or {}
233 # if push hook is enabled via web interface
232 # if push hook is enabled via web interface
234 if _hooks.get(RhodeCodeUi.HOOK_PUSH):
233 if _hooks.get(RhodeCodeUi.HOOK_PUSH):
235
234
236 extras = {
235 extras = {
237 'username': env['RHODECODE_USER'],
236 'username': env['RHODECODE_USER'],
238 'repository': repo.repo_name,
237 'repository': repo.repo_name,
239 'scm': 'git',
238 'scm': 'git',
240 'action': 'push',
239 'action': 'push',
241 'ip': env['RHODECODE_CONFIG_IP'],
240 'ip': env['RHODECODE_CONFIG_IP'],
242 }
241 }
243 for k, v in extras.items():
242 for k, v in extras.items():
244 baseui.setconfig('rhodecode_extras', k, v)
243 baseui.setconfig('rhodecode_extras', k, v)
245 repo = repo.scm_instance
244 repo = repo.scm_instance
246 repo.ui = baseui
245 repo.ui = baseui
247 old_rev, new_rev, ref = revs
246 old_rev, new_rev, ref = revs
248 if old_rev == EmptyChangeset().raw_id:
247 if old_rev == EmptyChangeset().raw_id:
249 cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'"
248 cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'"
250 heads = repo.run_git_command(cmd)[0]
249 heads = repo.run_git_command(cmd)[0]
251 heads = heads.replace(ref, '')
250 heads = heads.replace(ref, '')
252 heads = ' '.join(map(lambda c: c.strip('\n').strip(),
251 heads = ' '.join(map(lambda c: c.strip('\n').strip(),
253 heads.splitlines()))
252 heads.splitlines()))
254 cmd = ('log ' + new_rev +
253 cmd = ('log ' + new_rev +
255 ' --reverse --pretty=format:"%H" --not ' + heads)
254 ' --reverse --pretty=format:"%H" --not ' + heads)
256 else:
255 else:
257 cmd = ('log ' + old_rev + '..' + new_rev +
256 cmd = ('log ' + old_rev + '..' + new_rev +
258 ' --reverse --pretty=format:"%H"')
257 ' --reverse --pretty=format:"%H"')
259 git_revs = repo.run_git_command(cmd)[0].splitlines()
258 git_revs = repo.run_git_command(cmd)[0].splitlines()
260
259
261 log_push_action(baseui, repo, _git_revs=git_revs)
260 log_push_action(baseui, repo, _git_revs=git_revs)
@@ -1,225 +1,225 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3 <%def name="title()">
3 <%def name="title()">
4 ${_('Journal')} - ${c.rhodecode_name}
4 ${_('Journal')} - ${c.rhodecode_name}
5 </%def>
5 </%def>
6 <%def name="breadcrumbs()">
6 <%def name="breadcrumbs()">
7 ${c.rhodecode_name}
7 ${c.rhodecode_name}
8 </%def>
8 </%def>
9 <%def name="page_nav()">
9 <%def name="page_nav()">
10 ${self.menu('home')}
10 ${self.menu('home')}
11 </%def>
11 </%def>
12 <%def name="main()">
12 <%def name="main()">
13
13
14 <div class="box box-left">
14 <div class="box box-left">
15 <!-- box / title -->
15 <!-- box / title -->
16 <div class="title">
16 <div class="title">
17 <h5>${_('Journal')}</h5>
17 <h5>${_('Journal')}</h5>
18 <ul class="links">
18 <ul class="links">
19 <li>
19 <li>
20 <span><a id="refresh" href="${h.url('journal')}"><img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/></a></span>
20 <span><a id="refresh" href="${h.url('journal')}"><img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/></a></span>
21 </li>
21 </li>
22 <li>
22 <li>
23 <span><a href="${h.url('journal_rss')}"><img class="icon" title="${_('RSS feed')}" alt="${_('RSS feed')}" src="${h.url('/images/icons/atom.png')}"/></a></span>
23 <span><a href="${h.url('journal_rss')}"><img class="icon" title="${_('RSS feed')}" alt="${_('RSS feed')}" src="${h.url('/images/icons/atom.png')}"/></a></span>
24 </li>
24 </li>
25 <li>
25 <li>
26 <span><a href="${h.url('journal_atom')}"><img class="icon" title="${_('ATOM feed')}" alt="${_('ATOM feed')}" src="${h.url('/images/icons/rss_16.png')}"/></a></span>
26 <span><a href="${h.url('journal_atom')}"><img class="icon" title="${_('ATOM feed')}" alt="${_('ATOM feed')}" src="${h.url('/images/icons/rss_16.png')}"/></a></span>
27 </li>
27 </li>
28 </ul>
28 </ul>
29 </div>
29 </div>
30 <div id="journal">${c.journal_data}</div>
30 <div id="journal">${c.journal_data}</div>
31 </div>
31 </div>
32 <div class="box box-right">
32 <div class="box box-right">
33 <!-- box / title -->
33 <!-- box / title -->
34 <div class="title">
34 <div class="title">
35 <h5>
35 <h5>
36 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
36 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
37 <a id="show_my" class="link-white" href="#my">${_('My repos')}</a> / <a id="show_watched" class="link-white" href="#watched">${_('Watched')}</a>
37 <a id="show_my" class="link-white" href="#my">${_('My repos')}</a> / <a id="show_watched" class="link-white" href="#watched">${_('Watched')}</a>
38 </h5>
38 </h5>
39 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
39 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
40 <ul class="links">
40 <ul class="links">
41 <li>
41 <li>
42 <span>${h.link_to(_('ADD'),h.url('admin_settings_create_repository'))}</span>
42 <span>${h.link_to(_('ADD'),h.url('admin_settings_create_repository'))}</span>
43 </li>
43 </li>
44 </ul>
44 </ul>
45 %endif
45 %endif
46 </div>
46 </div>
47 <!-- end box / title -->
47 <!-- end box / title -->
48 <div id="my" class="table">
48 <div id="my" class="table">
49 %if c.user_repos:
49 %if c.user_repos:
50 <div id='repos_list_wrap' class="yui-skin-sam">
50 <div id='repos_list_wrap' class="yui-skin-sam">
51 <table id="repos_list">
51 <table id="repos_list">
52 <thead>
52 <thead>
53 <tr>
53 <tr>
54 <th></th>
54 <th></th>
55 <th class="left">${_('Name')}</th>
55 <th class="left">${_('Name')}</th>
56 <th class="left">${_('Revision')}</th>
56 <th class="left">${_('Revision')}</th>
57 <th class="left">${_('Action')}</th>
57 <th class="left">${_('Action')}</th>
58 <th class="left">${_('Action')}</th>
58 <th class="left">${_('Action')}</th>
59 </thead>
59 </thead>
60 <tbody>
60 <tbody>
61 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
61 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
62 %for repo in c.user_repos:
62 %for repo in c.user_repos:
63 <tr>
63 <tr>
64 ##QUICK MENU
64 ##QUICK MENU
65 <td class="quick_repo_menu">
65 <td class="quick_repo_menu">
66 ${dt.quick_menu(repo['name'])}
66 ${dt.quick_menu(repo['name'])}
67 </td>
67 </td>
68 ##REPO NAME AND ICONS
68 ##REPO NAME AND ICONS
69 <td class="reponame">
69 <td class="reponame">
70 ${dt.repo_name(repo['name'],repo['dbrepo']['repo_type'],repo['dbrepo']['private'],repo['dbrepo_fork'].get('repo_name'))}
70 ${dt.repo_name(repo['name'],repo['dbrepo']['repo_type'],repo['dbrepo']['private'],repo['dbrepo_fork'].get('repo_name'))}
71 </td>
71 </td>
72 ##LAST REVISION
72 ##LAST REVISION
73 <td>
73 <td>
74 ${dt.revision(repo['name'],repo['rev'],repo['tip'],repo['author'],repo['last_msg'])}
74 ${dt.revision(repo['name'],repo['rev'],repo['tip'],repo['author'],repo['last_msg'])}
75 </td>
75 </td>
76 ##
76 ##
77 <td><a href="${h.url('repo_settings_home',repo_name=repo['name'])}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url('/images/icons/application_form_edit.png')}"/></a></td>
77 <td><a href="${h.url('repo_settings_home',repo_name=repo['name'])}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url('/images/icons/application_form_edit.png')}"/></a></td>
78 <td>
78 <td>
79 ${h.form(url('repo_settings_delete', repo_name=repo['name']),method='delete')}
79 ${h.form(url('repo_settings_delete', repo_name=repo['name']),method='delete')}
80 ${h.submit('remove_%s' % repo['name'],'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
80 ${h.submit('remove_%s' % repo['name'],'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
81 ${h.end_form()}
81 ${h.end_form()}
82 </td>
82 </td>
83 </tr>
83 </tr>
84 %endfor
84 %endfor
85 </tbody>
85 </tbody>
86 </table>
86 </table>
87 </div>
87 </div>
88 %else:
88 %else:
89 <div style="padding:5px 0px 10px 0px;">
89 <div style="padding:5px 0px 10px 0px;">
90 ${_('No repositories yet')}
90 ${_('No repositories yet')}
91 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
91 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
92 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'),class_="ui-btn")}
92 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'),class_="ui-btn")}
93 %endif
93 %endif
94 </div>
94 </div>
95 %endif
95 %endif
96 </div>
96 </div>
97
97
98 <div id="watched" class="table" style="display:none">
98 <div id="watched" class="table" style="display:none">
99 %if c.following:
99 %if c.following:
100 <table>
100 <table>
101 <thead>
101 <thead>
102 <tr>
102 <tr>
103 <th class="left">${_('Name')}</th>
103 <th class="left">${_('Name')}</th>
104 </thead>
104 </thead>
105 <tbody>
105 <tbody>
106 %for entry in c.following:
106 %for entry in c.following:
107 <tr>
107 <tr>
108 <td>
108 <td>
109 %if entry.follows_user_id:
109 %if entry.follows_user_id:
110 <img title="${_('following user')}" alt="${_('user')}" src="${h.url('/images/icons/user.png')}"/>
110 <img title="${_('following user')}" alt="${_('user')}" src="${h.url('/images/icons/user.png')}"/>
111 ${entry.follows_user.full_contact}
111 ${entry.follows_user.full_contact}
112 %endif
112 %endif
113
113
114 %if entry.follows_repo_id:
114 %if entry.follows_repo_id:
115 <div style="float:right;padding-right:5px">
115 <div style="float:right;padding-right:5px">
116 <span id="follow_toggle_${entry.follows_repository.repo_id}" class="following" title="${_('Stop following this repository')}"
116 <span id="follow_toggle_${entry.follows_repository.repo_id}" class="following" title="${_('Stop following this repository')}"
117 onclick="javascript:toggleFollowingRepo(this,${entry.follows_repository.repo_id},'${str(h.get_token())}')">
117 onclick="javascript:toggleFollowingRepo(this,${entry.follows_repository.repo_id},'${str(h.get_token())}')">
118 </span>
118 </span>
119 </div>
119 </div>
120
120
121 %if h.is_hg(entry.follows_repository):
121 %if h.is_hg(entry.follows_repository):
122 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
122 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
123 %elif h.is_git(entry.follows_repository):
123 %elif h.is_git(entry.follows_repository):
124 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
124 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
125 %endif
125 %endif
126
126
127 %if entry.follows_repository.private:
127 %if entry.follows_repository.private:
128 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
128 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
129 %else:
129 %else:
130 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
130 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
131 %endif
131 %endif
132 <span class="watched_repo">
132 <span class="watched_repo">
133 ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',repo_name=entry.follows_repository.repo_name))}
133 ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',repo_name=entry.follows_repository.repo_name))}
134 </span>
134 </span>
135 %endif
135 %endif
136 </td>
136 </td>
137 </tr>
137 </tr>
138 %endfor
138 %endfor
139 </tbody>
139 </tbody>
140 </table>
140 </table>
141 %else:
141 %else:
142 <div style="padding:5px 0px 10px 0px;">
142 <div style="padding:5px 0px 10px 0px;">
143 ${_('You are not following any users or repositories')}
143 ${_('You are not following any users or repositories')}
144 </div>
144 </div>
145 %endif
145 %endif
146 </div>
146 </div>
147 </div>
147 </div>
148
148
149 <script type="text/javascript">
149 <script type="text/javascript">
150
150
151 YUE.on('show_my','click',function(e){
151 YUE.on('show_my','click',function(e){
152 YUD.setStyle('watched','display','none');
152 YUD.setStyle('watched','display','none');
153 YUD.setStyle('my','display','');
153 YUD.setStyle('my','display','');
154 var nodes = YUQ('#my tr td a.repo_name');
154 var nodes = YUQ('#my tr td a.repo_name');
155 var target = 'q_filter';
155 var target = 'q_filter';
156 var func = function(node){
156 var func = function(node){
157 return node.parentNode.parentNode.parentNode.parentNode;
157 return node.parentNode.parentNode.parentNode.parentNode;
158 }
158 }
159 q_filter(target,nodes,func);
159 q_filter(target,nodes,func);
160 YUE.preventDefault(e);
160 YUE.preventDefault(e);
161 })
161 })
162 YUE.on('show_watched','click',function(e){
162 YUE.on('show_watched','click',function(e){
163 YUD.setStyle('my','display','none');
163 YUD.setStyle('my','display','none');
164 YUD.setStyle('watched','display','');
164 YUD.setStyle('watched','display','');
165 var nodes = YUQ('#watched .watched_repo a');
165 var nodes = YUQ('#watched .watched_repo a');
166 var target = 'q_filter';
166 var target = 'q_filter';
167 var func = function(node){
167 var func = function(node){
168 return node.parentNode.parentNode;
168 return node.parentNode.parentNode;
169 }
169 }
170 q_filter(target,nodes,func);
170 q_filter(target,nodes,func);
171 YUE.preventDefault(e);
171 YUE.preventDefault(e);
172 })
172 })
173 YUE.on('refresh','click',function(e){
173 YUE.on('refresh','click',function(e){
174 ypjax(e.currentTarget.href,"journal",function(){show_more_event();tooltip_activate();});
174 ypjax(e.currentTarget.href,"journal",function(){show_more_event();tooltip_activate();});
175 YUE.preventDefault(e);
175 YUE.preventDefault(e);
176 });
176 });
177
177
178
178
179 // main table sorting
179 // main table sorting
180 var myColumnDefs = [
180 var myColumnDefs = [
181 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
181 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
182 {key:"name",label:"${_('Name')}",sortable:true,
182 {key:"name",label:"${_('Name')}",sortable:true,
183 sortOptions: { sortFunction: nameSort }},
183 sortOptions: { sortFunction: nameSort }},
184 {key:"tip",label:"${_('Tip')}",sortable:true,
184 {key:"tip",label:"${_('Tip')}",sortable:true,
185 sortOptions: { sortFunction: revisionSort }},
185 sortOptions: { sortFunction: revisionSort }},
186 {key:"action1",label:"",sortable:false},
186 {key:"action1",label:"",sortable:false},
187 {key:"action2",label:"",sortable:false},
187 {key:"action2",label:"",sortable:false},
188 ];
188 ];
189
189
190 var myDataSource = new YAHOO.util.DataSource(YUD.get("repos_list"));
190 var myDataSource = new YAHOO.util.DataSource(YUD.get("repos_list"));
191
191
192 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
192 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
193
193
194 myDataSource.responseSchema = {
194 myDataSource.responseSchema = {
195 fields: [
195 fields: [
196 {key:"menu"},
196 {key:"menu"},
197 {key:"name"},
197 {key:"name"},
198 {key:"tip"},
198 {key:"tip"},
199 {key:"action1"},
199 {key:"action1"},
200 {key:"action2"}
200 {key:"action2"}
201 ]
201 ]
202 };
202 };
203
203
204 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
204 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
205 {
205 {
206 sortedBy:{key:"name",dir:"asc"},
206 sortedBy:{key:"name",dir:"asc"},
207 MSG_SORTASC:"${_('Click to sort ascending')}",
207 MSG_SORTASC:"${_('Click to sort ascending')}",
208 MSG_SORTDESC:"${_('Click to sort descending')}",
208 MSG_SORTDESC:"${_('Click to sort descending')}",
209 MSG_EMPTY:"${_('No records found.')}",
209 MSG_EMPTY:"${_('No records found.')}",
210 MSG_ERROR:"${_('Data error.')}",
210 MSG_ERROR:"${_('Data error.')}",
211 MSG_LOADING:"${_('Loading...')}",
211 MSG_LOADING:"${_('Loading...')}",
212 }
212 }
213 );
213 );
214 myDataTable.subscribe('postRenderEvent',function(oArgs) {
214 myDataTable.subscribe('postRenderEvent',function(oArgs) {
215 tooltip_activate();
215 tooltip_activate();
216 quick_repo_menu();
216 quick_repo_menu();
217 var func = function(node){
217 var func = function(node){
218 return node.parentNode.parentNode.parentNode.parentNode;
218 return node.parentNode.parentNode.parentNode.parentNode;
219 }
219 }
220 q_filter('q_filter',YUQ('#my tr td a.repo_name'),func);
220 q_filter('q_filter',YUQ('#my tr td a.repo_name'),func);
221 });
221 });
222
222
223
223
224 </script>
224 </script>
225 </%def>
225 </%def>
@@ -1,40 +1,40 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3 <%def name="title()">
3 <%def name="title()">
4 ${_('Journal')} - ${c.rhodecode_name}
4 ${_('Journal')} - ${c.rhodecode_name}
5 </%def>
5 </%def>
6 <%def name="breadcrumbs()">
6 <%def name="breadcrumbs()">
7 ${c.rhodecode_name}
7 ${c.rhodecode_name}
8 </%def>
8 </%def>
9 <%def name="page_nav()">
9 <%def name="page_nav()">
10 ${self.menu('home')}
10 ${self.menu('home')}
11 </%def>
11 </%def>
12 <%def name="main()">
12 <%def name="main()">
13
13
14 <div class="box">
14 <div class="box">
15 <!-- box / title -->
15 <!-- box / title -->
16 <div class="title">
16 <div class="title">
17 <h5>${_('Public Journal')}</h5>
17 <h5>${_('Public Journal')}</h5>
18 <ul class="links">
18 <ul class="links">
19 <li>
19 <li>
20 <span><a href="${h.url('public_journal_rss')}"><img class="icon" title="${_('RSS feed')}" alt="${_('RSS feed')}" src="${h.url('/images/icons/atom.png')}"/></a></span>
20 <span><a href="${h.url('public_journal_rss')}"><img class="icon" title="${_('RSS feed')}" alt="${_('RSS feed')}" src="${h.url('/images/icons/atom.png')}"/></a></span>
21 </li>
21 </li>
22 <li>
22 <li>
23 <span><a href="${h.url('public_journal_atom')}"><img class="icon" title="${_('ATOM feed')}" alt="${_('ATOM feed')}" src="${h.url('/images/icons/rss_16.png')}"/></a></span>
23 <span><a href="${h.url('public_journal_atom')}"><img class="icon" title="${_('ATOM feed')}" alt="${_('ATOM feed')}" src="${h.url('/images/icons/rss_16.png')}"/></a></span>
24 </li>
24 </li>
25 </ul>
25 </ul>
26
26
27 </div>
27 </div>
28 <script type="text/javascript">
28 <script type="text/javascript">
29 function show_more_event(){
29 function show_more_event(){
30 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
30 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
31 var el = e.target;
31 var el = e.target;
32 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
32 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
33 YUD.setStyle(el.parentNode,'display','none');
33 YUD.setStyle(el.parentNode,'display','none');
34 });
34 });
35 }
35 }
36 </script>
36 </script>
37 <div id="journal">${c.journal_data}</div>
37 <div id="journal">${c.journal_data}</div>
38 </div>
38 </div>
39
39
40 </%def>
40 </%def>
General Comments 0
You need to be logged in to leave comments. Login now