##// END OF EJS Templates
git hook installation should be only executed for git backend
marcink -
r2992:3bc8d2e0 beta
parent child Browse files
Show More
@@ -1,56 +1,55
1 .. _git_support:
1 .. _git_support:
2
2
3 ===========
3 ===========
4 GIT support
4 GIT support
5 ===========
5 ===========
6
6
7
7
8 Git support in RhodeCode 1.3 was enabled by default. You need to have a git
8 Git support in RhodeCode 1.3 was enabled by default. You need to have a git
9 client installed on the machine to make git fully work.
9 client installed on the machine to make git fully work.
10
10
11 Although There are some limitations on git usage.
11 Although There is one limitation on git usage.
12
12
13 - hooks that are executed on pull/push are not *real* hooks, they are
13 - large pushes requires a http server with chunked encoding support.
14 just emulating the behavior, and are executed **BEFORE** action takes place.
15 - large pushes needs http server with chunked encoding support.
16
14
17 if you plan to use git you need to run RhodeCode with some
15 if you plan to use git you need to run RhodeCode with some
18 http server that supports chunked encoding which git http protocol uses,
16 http server that supports chunked encoding which git http protocol uses,
19 i recommend using waitress_ or gunicorn_ (linux only) for `paste` wsgi app
17 i recommend using waitress_ or gunicorn_ (linux only) for `paste` wsgi app
20 replacement.
18 replacement. Starting from version 1.4 waitress_ is the default wsgi server
19 used in RhodeCode.
21
20
22 To use, simply change change the following in the .ini file::
21 To use, simply change change the following in the .ini file::
23
22
24 use = egg:Paste#http
23 use = egg:Paste#http
25
24
26 to::
25 to::
27
26
28 use = egg:waitress#main
27 use = egg:waitress#main
29
28
30 or::
29 or::
31
30
32 use = egg:gunicorn#main
31 use = egg:gunicorn#main
33
32
34
33
35 And comment out bellow options::
34 And comment out bellow options::
36
35
37 threadpool_workers =
36 threadpool_workers =
38 threadpool_max_requests =
37 threadpool_max_requests =
39 use_threadpool =
38 use_threadpool =
40
39
41
40
42 You can simply run `paster serve` as usual.
41 You can simply run `paster serve` as usual.
43
42
44
43
45 You can always disable git/hg support by editing a
44 You can always disable git/hg support by editing a
46 file **rhodecode/__init__.py** and commenting out backends
45 file **rhodecode/__init__.py** and commenting out backends
47
46
48 .. code-block:: python
47 .. code-block:: python
49
48
50 BACKENDS = {
49 BACKENDS = {
51 'hg': 'Mercurial repository',
50 'hg': 'Mercurial repository',
52 #'git': 'Git repository',
51 #'git': 'Git repository',
53 }
52 }
54
53
55 .. _waitress: http://pypi.python.org/pypi/waitress
54 .. _waitress: http://pypi.python.org/pypi/waitress
56 .. _gunicorn: http://pypi.python.org/pypi/gunicorn No newline at end of file
55 .. _gunicorn: http://pypi.python.org/pypi/gunicorn
@@ -1,448 +1,448
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.celerylib.tasks
3 rhodecode.lib.celerylib.tasks
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 RhodeCode task modules, containing all task that suppose to be run
6 RhodeCode task modules, containing all task that suppose to be run
7 by celery daemon
7 by celery daemon
8
8
9 :created_on: Oct 6, 2010
9 :created_on: Oct 6, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software: you can redistribute it and/or modify
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
17 # (at your option) any later version.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 from celery.decorators import task
26 from celery.decorators import task
27
27
28 import os
28 import os
29 import traceback
29 import traceback
30 import logging
30 import logging
31 from os.path import join as jn
31 from os.path import join as jn
32
32
33 from time import mktime
33 from time import mktime
34 from operator import itemgetter
34 from operator import itemgetter
35 from string import lower
35 from string import lower
36
36
37 from pylons import config, url
37 from pylons import config, url
38 from pylons.i18n.translation import _
38 from pylons.i18n.translation import _
39
39
40 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs import get_backend
41
41
42 from rhodecode import CELERY_ON, CELERY_EAGER
42 from rhodecode import CELERY_ON, CELERY_EAGER
43 from rhodecode.lib.utils2 import safe_str
43 from rhodecode.lib.utils2 import safe_str
44 from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \
44 from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \
45 str2bool, __get_lockkey, LockHeld, DaemonLock, get_session
45 str2bool, __get_lockkey, LockHeld, DaemonLock, get_session
46 from rhodecode.lib.helpers import person
46 from rhodecode.lib.helpers import person
47 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
47 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
48 from rhodecode.lib.utils import add_cache, action_logger
48 from rhodecode.lib.utils import add_cache, action_logger
49 from rhodecode.lib.compat import json, OrderedDict
49 from rhodecode.lib.compat import json, OrderedDict
50 from rhodecode.lib.hooks import log_create_repository
50 from rhodecode.lib.hooks import log_create_repository
51
51
52 from rhodecode.model.db import Statistics, Repository, User
52 from rhodecode.model.db import Statistics, Repository, User
53 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.scm import ScmModel
54
54
55
55
56 add_cache(config)
56 add_cache(config)
57
57
58 __all__ = ['whoosh_index', 'get_commits_stats',
58 __all__ = ['whoosh_index', 'get_commits_stats',
59 'reset_user_password', 'send_email']
59 'reset_user_password', 'send_email']
60
60
61
61
62 def get_logger(cls):
62 def get_logger(cls):
63 if CELERY_ON:
63 if CELERY_ON:
64 try:
64 try:
65 log = cls.get_logger()
65 log = cls.get_logger()
66 except:
66 except:
67 log = logging.getLogger(__name__)
67 log = logging.getLogger(__name__)
68 else:
68 else:
69 log = logging.getLogger(__name__)
69 log = logging.getLogger(__name__)
70
70
71 return log
71 return log
72
72
73
73
74 @task(ignore_result=True)
74 @task(ignore_result=True)
75 @locked_task
75 @locked_task
76 @dbsession
76 @dbsession
77 def whoosh_index(repo_location, full_index):
77 def whoosh_index(repo_location, full_index):
78 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
78 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
79 log = get_logger(whoosh_index)
79 log = get_logger(whoosh_index)
80 DBS = get_session()
80 DBS = get_session()
81
81
82 index_location = config['index_dir']
82 index_location = config['index_dir']
83 WhooshIndexingDaemon(index_location=index_location,
83 WhooshIndexingDaemon(index_location=index_location,
84 repo_location=repo_location, sa=DBS)\
84 repo_location=repo_location, sa=DBS)\
85 .run(full_index=full_index)
85 .run(full_index=full_index)
86
86
87
87
88 @task(ignore_result=True)
88 @task(ignore_result=True)
89 @dbsession
89 @dbsession
90 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
90 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
91 log = get_logger(get_commits_stats)
91 log = get_logger(get_commits_stats)
92 DBS = get_session()
92 DBS = get_session()
93 lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y,
93 lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y,
94 ts_max_y)
94 ts_max_y)
95 lockkey_path = config['here']
95 lockkey_path = config['here']
96
96
97 log.info('running task with lockkey %s' % lockkey)
97 log.info('running task with lockkey %s' % lockkey)
98
98
99 try:
99 try:
100 lock = l = DaemonLock(file_=jn(lockkey_path, lockkey))
100 lock = l = DaemonLock(file_=jn(lockkey_path, lockkey))
101
101
102 # for js data compatibility cleans the key for person from '
102 # for js data compatibility cleans the key for person from '
103 akc = lambda k: person(k).replace('"', "")
103 akc = lambda k: person(k).replace('"', "")
104
104
105 co_day_auth_aggr = {}
105 co_day_auth_aggr = {}
106 commits_by_day_aggregate = {}
106 commits_by_day_aggregate = {}
107 repo = Repository.get_by_repo_name(repo_name)
107 repo = Repository.get_by_repo_name(repo_name)
108 if repo is None:
108 if repo is None:
109 return True
109 return True
110
110
111 repo = repo.scm_instance
111 repo = repo.scm_instance
112 repo_size = repo.count()
112 repo_size = repo.count()
113 # return if repo have no revisions
113 # return if repo have no revisions
114 if repo_size < 1:
114 if repo_size < 1:
115 lock.release()
115 lock.release()
116 return True
116 return True
117
117
118 skip_date_limit = True
118 skip_date_limit = True
119 parse_limit = int(config['app_conf'].get('commit_parse_limit'))
119 parse_limit = int(config['app_conf'].get('commit_parse_limit'))
120 last_rev = None
120 last_rev = None
121 last_cs = None
121 last_cs = None
122 timegetter = itemgetter('time')
122 timegetter = itemgetter('time')
123
123
124 dbrepo = DBS.query(Repository)\
124 dbrepo = DBS.query(Repository)\
125 .filter(Repository.repo_name == repo_name).scalar()
125 .filter(Repository.repo_name == repo_name).scalar()
126 cur_stats = DBS.query(Statistics)\
126 cur_stats = DBS.query(Statistics)\
127 .filter(Statistics.repository == dbrepo).scalar()
127 .filter(Statistics.repository == dbrepo).scalar()
128
128
129 if cur_stats is not None:
129 if cur_stats is not None:
130 last_rev = cur_stats.stat_on_revision
130 last_rev = cur_stats.stat_on_revision
131
131
132 if last_rev == repo.get_changeset().revision and repo_size > 1:
132 if last_rev == repo.get_changeset().revision and repo_size > 1:
133 # pass silently without any work if we're not on first revision or
133 # pass silently without any work if we're not on first revision or
134 # current state of parsing revision(from db marker) is the
134 # current state of parsing revision(from db marker) is the
135 # last revision
135 # last revision
136 lock.release()
136 lock.release()
137 return True
137 return True
138
138
139 if cur_stats:
139 if cur_stats:
140 commits_by_day_aggregate = OrderedDict(json.loads(
140 commits_by_day_aggregate = OrderedDict(json.loads(
141 cur_stats.commit_activity_combined))
141 cur_stats.commit_activity_combined))
142 co_day_auth_aggr = json.loads(cur_stats.commit_activity)
142 co_day_auth_aggr = json.loads(cur_stats.commit_activity)
143
143
144 log.debug('starting parsing %s' % parse_limit)
144 log.debug('starting parsing %s' % parse_limit)
145 lmktime = mktime
145 lmktime = mktime
146
146
147 last_rev = last_rev + 1 if last_rev >= 0 else 0
147 last_rev = last_rev + 1 if last_rev >= 0 else 0
148 log.debug('Getting revisions from %s to %s' % (
148 log.debug('Getting revisions from %s to %s' % (
149 last_rev, last_rev + parse_limit)
149 last_rev, last_rev + parse_limit)
150 )
150 )
151 for cs in repo[last_rev:last_rev + parse_limit]:
151 for cs in repo[last_rev:last_rev + parse_limit]:
152 log.debug('parsing %s' % cs)
152 log.debug('parsing %s' % cs)
153 last_cs = cs # remember last parsed changeset
153 last_cs = cs # remember last parsed changeset
154 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
154 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
155 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
155 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
156
156
157 if akc(cs.author) in co_day_auth_aggr:
157 if akc(cs.author) in co_day_auth_aggr:
158 try:
158 try:
159 l = [timegetter(x) for x in
159 l = [timegetter(x) for x in
160 co_day_auth_aggr[akc(cs.author)]['data']]
160 co_day_auth_aggr[akc(cs.author)]['data']]
161 time_pos = l.index(k)
161 time_pos = l.index(k)
162 except ValueError:
162 except ValueError:
163 time_pos = False
163 time_pos = False
164
164
165 if time_pos >= 0 and time_pos is not False:
165 if time_pos >= 0 and time_pos is not False:
166
166
167 datadict = \
167 datadict = \
168 co_day_auth_aggr[akc(cs.author)]['data'][time_pos]
168 co_day_auth_aggr[akc(cs.author)]['data'][time_pos]
169
169
170 datadict["commits"] += 1
170 datadict["commits"] += 1
171 datadict["added"] += len(cs.added)
171 datadict["added"] += len(cs.added)
172 datadict["changed"] += len(cs.changed)
172 datadict["changed"] += len(cs.changed)
173 datadict["removed"] += len(cs.removed)
173 datadict["removed"] += len(cs.removed)
174
174
175 else:
175 else:
176 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
176 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
177
177
178 datadict = {"time": k,
178 datadict = {"time": k,
179 "commits": 1,
179 "commits": 1,
180 "added": len(cs.added),
180 "added": len(cs.added),
181 "changed": len(cs.changed),
181 "changed": len(cs.changed),
182 "removed": len(cs.removed),
182 "removed": len(cs.removed),
183 }
183 }
184 co_day_auth_aggr[akc(cs.author)]['data']\
184 co_day_auth_aggr[akc(cs.author)]['data']\
185 .append(datadict)
185 .append(datadict)
186
186
187 else:
187 else:
188 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
188 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
189 co_day_auth_aggr[akc(cs.author)] = {
189 co_day_auth_aggr[akc(cs.author)] = {
190 "label": akc(cs.author),
190 "label": akc(cs.author),
191 "data": [{"time":k,
191 "data": [{"time":k,
192 "commits":1,
192 "commits":1,
193 "added":len(cs.added),
193 "added":len(cs.added),
194 "changed":len(cs.changed),
194 "changed":len(cs.changed),
195 "removed":len(cs.removed),
195 "removed":len(cs.removed),
196 }],
196 }],
197 "schema": ["commits"],
197 "schema": ["commits"],
198 }
198 }
199
199
200 #gather all data by day
200 #gather all data by day
201 if k in commits_by_day_aggregate:
201 if k in commits_by_day_aggregate:
202 commits_by_day_aggregate[k] += 1
202 commits_by_day_aggregate[k] += 1
203 else:
203 else:
204 commits_by_day_aggregate[k] = 1
204 commits_by_day_aggregate[k] = 1
205
205
206 overview_data = sorted(commits_by_day_aggregate.items(),
206 overview_data = sorted(commits_by_day_aggregate.items(),
207 key=itemgetter(0))
207 key=itemgetter(0))
208
208
209 if not co_day_auth_aggr:
209 if not co_day_auth_aggr:
210 co_day_auth_aggr[akc(repo.contact)] = {
210 co_day_auth_aggr[akc(repo.contact)] = {
211 "label": akc(repo.contact),
211 "label": akc(repo.contact),
212 "data": [0, 1],
212 "data": [0, 1],
213 "schema": ["commits"],
213 "schema": ["commits"],
214 }
214 }
215
215
216 stats = cur_stats if cur_stats else Statistics()
216 stats = cur_stats if cur_stats else Statistics()
217 stats.commit_activity = json.dumps(co_day_auth_aggr)
217 stats.commit_activity = json.dumps(co_day_auth_aggr)
218 stats.commit_activity_combined = json.dumps(overview_data)
218 stats.commit_activity_combined = json.dumps(overview_data)
219
219
220 log.debug('last revison %s' % last_rev)
220 log.debug('last revison %s' % last_rev)
221 leftovers = len(repo.revisions[last_rev:])
221 leftovers = len(repo.revisions[last_rev:])
222 log.debug('revisions to parse %s' % leftovers)
222 log.debug('revisions to parse %s' % leftovers)
223
223
224 if last_rev == 0 or leftovers < parse_limit:
224 if last_rev == 0 or leftovers < parse_limit:
225 log.debug('getting code trending stats')
225 log.debug('getting code trending stats')
226 stats.languages = json.dumps(__get_codes_stats(repo_name))
226 stats.languages = json.dumps(__get_codes_stats(repo_name))
227
227
228 try:
228 try:
229 stats.repository = dbrepo
229 stats.repository = dbrepo
230 stats.stat_on_revision = last_cs.revision if last_cs else 0
230 stats.stat_on_revision = last_cs.revision if last_cs else 0
231 DBS.add(stats)
231 DBS.add(stats)
232 DBS.commit()
232 DBS.commit()
233 except:
233 except:
234 log.error(traceback.format_exc())
234 log.error(traceback.format_exc())
235 DBS.rollback()
235 DBS.rollback()
236 lock.release()
236 lock.release()
237 return False
237 return False
238
238
239 # final release
239 # final release
240 lock.release()
240 lock.release()
241
241
242 # execute another task if celery is enabled
242 # execute another task if celery is enabled
243 if len(repo.revisions) > 1 and CELERY_ON:
243 if len(repo.revisions) > 1 and CELERY_ON:
244 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
244 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
245 return True
245 return True
246 except LockHeld:
246 except LockHeld:
247 log.info('LockHeld')
247 log.info('LockHeld')
248 return 'Task with key %s already running' % lockkey
248 return 'Task with key %s already running' % lockkey
249
249
250 @task(ignore_result=True)
250 @task(ignore_result=True)
251 @dbsession
251 @dbsession
252 def send_password_link(user_email):
252 def send_password_link(user_email):
253 from rhodecode.model.notification import EmailNotificationModel
253 from rhodecode.model.notification import EmailNotificationModel
254
254
255 log = get_logger(send_password_link)
255 log = get_logger(send_password_link)
256 DBS = get_session()
256 DBS = get_session()
257
257
258 try:
258 try:
259 user = User.get_by_email(user_email)
259 user = User.get_by_email(user_email)
260 if user:
260 if user:
261 log.debug('password reset user found %s' % user)
261 log.debug('password reset user found %s' % user)
262 link = url('reset_password_confirmation', key=user.api_key,
262 link = url('reset_password_confirmation', key=user.api_key,
263 qualified=True)
263 qualified=True)
264 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
264 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
265 body = EmailNotificationModel().get_email_tmpl(reg_type,
265 body = EmailNotificationModel().get_email_tmpl(reg_type,
266 **{'user':user.short_contact,
266 **{'user':user.short_contact,
267 'reset_url':link})
267 'reset_url':link})
268 log.debug('sending email')
268 log.debug('sending email')
269 run_task(send_email, user_email,
269 run_task(send_email, user_email,
270 _("password reset link"), body)
270 _("password reset link"), body)
271 log.info('send new password mail to %s' % user_email)
271 log.info('send new password mail to %s' % user_email)
272 else:
272 else:
273 log.debug("password reset email %s not found" % user_email)
273 log.debug("password reset email %s not found" % user_email)
274 except:
274 except:
275 log.error(traceback.format_exc())
275 log.error(traceback.format_exc())
276 return False
276 return False
277
277
278 return True
278 return True
279
279
280 @task(ignore_result=True)
280 @task(ignore_result=True)
281 @dbsession
281 @dbsession
282 def reset_user_password(user_email):
282 def reset_user_password(user_email):
283 from rhodecode.lib import auth
283 from rhodecode.lib import auth
284
284
285 log = get_logger(reset_user_password)
285 log = get_logger(reset_user_password)
286 DBS = get_session()
286 DBS = get_session()
287
287
288 try:
288 try:
289 try:
289 try:
290 user = User.get_by_email(user_email)
290 user = User.get_by_email(user_email)
291 new_passwd = auth.PasswordGenerator().gen_password(8,
291 new_passwd = auth.PasswordGenerator().gen_password(8,
292 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
292 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
293 if user:
293 if user:
294 user.password = auth.get_crypt_password(new_passwd)
294 user.password = auth.get_crypt_password(new_passwd)
295 user.api_key = auth.generate_api_key(user.username)
295 user.api_key = auth.generate_api_key(user.username)
296 DBS.add(user)
296 DBS.add(user)
297 DBS.commit()
297 DBS.commit()
298 log.info('change password for %s' % user_email)
298 log.info('change password for %s' % user_email)
299 if new_passwd is None:
299 if new_passwd is None:
300 raise Exception('unable to generate new password')
300 raise Exception('unable to generate new password')
301 except:
301 except:
302 log.error(traceback.format_exc())
302 log.error(traceback.format_exc())
303 DBS.rollback()
303 DBS.rollback()
304
304
305 run_task(send_email, user_email,
305 run_task(send_email, user_email,
306 'Your new password',
306 'Your new password',
307 'Your new RhodeCode password:%s' % (new_passwd))
307 'Your new RhodeCode password:%s' % (new_passwd))
308 log.info('send new password mail to %s' % user_email)
308 log.info('send new password mail to %s' % user_email)
309
309
310 except:
310 except:
311 log.error('Failed to update user password')
311 log.error('Failed to update user password')
312 log.error(traceback.format_exc())
312 log.error(traceback.format_exc())
313
313
314 return True
314 return True
315
315
316
316
317 @task(ignore_result=True)
317 @task(ignore_result=True)
318 @dbsession
318 @dbsession
319 def send_email(recipients, subject, body, html_body=''):
319 def send_email(recipients, subject, body, html_body=''):
320 """
320 """
321 Sends an email with defined parameters from the .ini files.
321 Sends an email with defined parameters from the .ini files.
322
322
323 :param recipients: list of recipients, it this is empty the defined email
323 :param recipients: list of recipients, it this is empty the defined email
324 address from field 'email_to' is used instead
324 address from field 'email_to' is used instead
325 :param subject: subject of the mail
325 :param subject: subject of the mail
326 :param body: body of the mail
326 :param body: body of the mail
327 :param html_body: html version of body
327 :param html_body: html version of body
328 """
328 """
329 log = get_logger(send_email)
329 log = get_logger(send_email)
330 DBS = get_session()
330 DBS = get_session()
331
331
332 email_config = config
332 email_config = config
333 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
333 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
334 if not recipients:
334 if not recipients:
335 # if recipients are not defined we send to email_config + all admins
335 # if recipients are not defined we send to email_config + all admins
336 admins = [u.email for u in User.query()
336 admins = [u.email for u in User.query()
337 .filter(User.admin == True).all()]
337 .filter(User.admin == True).all()]
338 recipients = [email_config.get('email_to')] + admins
338 recipients = [email_config.get('email_to')] + admins
339
339
340 mail_from = email_config.get('app_email_from', 'RhodeCode')
340 mail_from = email_config.get('app_email_from', 'RhodeCode')
341 user = email_config.get('smtp_username')
341 user = email_config.get('smtp_username')
342 passwd = email_config.get('smtp_password')
342 passwd = email_config.get('smtp_password')
343 mail_server = email_config.get('smtp_server')
343 mail_server = email_config.get('smtp_server')
344 mail_port = email_config.get('smtp_port')
344 mail_port = email_config.get('smtp_port')
345 tls = str2bool(email_config.get('smtp_use_tls'))
345 tls = str2bool(email_config.get('smtp_use_tls'))
346 ssl = str2bool(email_config.get('smtp_use_ssl'))
346 ssl = str2bool(email_config.get('smtp_use_ssl'))
347 debug = str2bool(config.get('debug'))
347 debug = str2bool(config.get('debug'))
348 smtp_auth = email_config.get('smtp_auth')
348 smtp_auth = email_config.get('smtp_auth')
349
349
350 try:
350 try:
351 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
351 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
352 mail_port, ssl, tls, debug=debug)
352 mail_port, ssl, tls, debug=debug)
353 m.send(recipients, subject, body, html_body)
353 m.send(recipients, subject, body, html_body)
354 except:
354 except:
355 log.error('Mail sending failed')
355 log.error('Mail sending failed')
356 log.error(traceback.format_exc())
356 log.error(traceback.format_exc())
357 return False
357 return False
358 return True
358 return True
359
359
360
360
361 @task(ignore_result=True)
361 @task(ignore_result=True)
362 @dbsession
362 @dbsession
363 def create_repo_fork(form_data, cur_user):
363 def create_repo_fork(form_data, cur_user):
364 """
364 """
365 Creates a fork of repository using interval VCS methods
365 Creates a fork of repository using interval VCS methods
366
366
367 :param form_data:
367 :param form_data:
368 :param cur_user:
368 :param cur_user:
369 """
369 """
370 from rhodecode.model.repo import RepoModel
370 from rhodecode.model.repo import RepoModel
371 from rhodecode.model.user import UserModel
371 from rhodecode.model.user import UserModel
372
372
373 log = get_logger(create_repo_fork)
373 log = get_logger(create_repo_fork)
374 DBS = get_session()
374 DBS = get_session()
375
375
376 base_path = Repository.base_path()
376 base_path = Repository.base_path()
377 cur_user = UserModel(DBS)._get_user(cur_user)
377 cur_user = UserModel(DBS)._get_user(cur_user)
378
378
379 fork_name = form_data['repo_name_full']
379 fork_name = form_data['repo_name_full']
380 repo_type = form_data['repo_type']
380 repo_type = form_data['repo_type']
381 description = form_data['description']
381 description = form_data['description']
382 owner = cur_user
382 owner = cur_user
383 private = form_data['private']
383 private = form_data['private']
384 clone_uri = form_data.get('clone_uri')
384 clone_uri = form_data.get('clone_uri')
385 repos_group = form_data['repo_group']
385 repos_group = form_data['repo_group']
386 landing_rev = form_data['landing_rev']
386 landing_rev = form_data['landing_rev']
387 copy_fork_permissions = form_data.get('copy_permissions')
387 copy_fork_permissions = form_data.get('copy_permissions')
388 fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id'))
388 fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id'))
389
389
390 fork_repo = RepoModel(DBS).create_repo(
390 fork_repo = RepoModel(DBS).create_repo(
391 fork_name, repo_type, description, owner, private, clone_uri,
391 fork_name, repo_type, description, owner, private, clone_uri,
392 repos_group, landing_rev, just_db=True, fork_of=fork_of,
392 repos_group, landing_rev, just_db=True, fork_of=fork_of,
393 copy_fork_permissions=copy_fork_permissions
393 copy_fork_permissions=copy_fork_permissions
394 )
394 )
395
395
396 update_after_clone = form_data['update_after_clone']
396 update_after_clone = form_data['update_after_clone']
397
397
398 source_repo_path = os.path.join(base_path, fork_of.repo_name)
398 source_repo_path = os.path.join(base_path, fork_of.repo_name)
399 destination_fork_path = os.path.join(base_path, fork_name)
399 destination_fork_path = os.path.join(base_path, fork_name)
400
400
401 log.info('creating fork of %s as %s', source_repo_path,
401 log.info('creating fork of %s as %s', source_repo_path,
402 destination_fork_path)
402 destination_fork_path)
403 backend = get_backend(repo_type)
403 backend = get_backend(repo_type)
404
404
405 if repo_type == 'git':
405 if repo_type == 'git':
406 r = backend(safe_str(destination_fork_path), create=True,
406 r = backend(safe_str(destination_fork_path), create=True,
407 src_url=safe_str(source_repo_path),
407 src_url=safe_str(source_repo_path),
408 update_after_clone=update_after_clone,
408 update_after_clone=update_after_clone,
409 bare=True)
409 bare=True)
410 # add rhodecode hook into this repo
411 ScmModel().install_git_hook(repo=r)
410 elif repo_type == 'hg':
412 elif repo_type == 'hg':
411 r = backend(safe_str(destination_fork_path), create=True,
413 r = backend(safe_str(destination_fork_path), create=True,
412 src_url=safe_str(source_repo_path),
414 src_url=safe_str(source_repo_path),
413 update_after_clone=update_after_clone)
415 update_after_clone=update_after_clone)
414 else:
416 else:
415 raise Exception('Unknown backend type %s' % repo_type)
417 raise Exception('Unknown backend type %s' % repo_type)
416
418
417 # add rhodecode hook into this repo
418 ScmModel().install_git_hook(repo=r)
419 log_create_repository(fork_repo.get_dict(), created_by=cur_user.username)
419 log_create_repository(fork_repo.get_dict(), created_by=cur_user.username)
420
420
421 action_logger(cur_user, 'user_forked_repo:%s' % fork_name,
421 action_logger(cur_user, 'user_forked_repo:%s' % fork_name,
422 fork_of.repo_name, '', DBS)
422 fork_of.repo_name, '', DBS)
423
423
424 action_logger(cur_user, 'user_created_fork:%s' % fork_name,
424 action_logger(cur_user, 'user_created_fork:%s' % fork_name,
425 fork_name, '', DBS)
425 fork_name, '', DBS)
426 # finally commit at latest possible stage
426 # finally commit at latest possible stage
427 DBS.commit()
427 DBS.commit()
428
428
429
429
430 def __get_codes_stats(repo_name):
430 def __get_codes_stats(repo_name):
431 from rhodecode.config.conf import LANGUAGES_EXTENSIONS_MAP
431 from rhodecode.config.conf import LANGUAGES_EXTENSIONS_MAP
432 repo = Repository.get_by_repo_name(repo_name).scm_instance
432 repo = Repository.get_by_repo_name(repo_name).scm_instance
433
433
434 tip = repo.get_changeset()
434 tip = repo.get_changeset()
435 code_stats = {}
435 code_stats = {}
436
436
437 def aggregate(cs):
437 def aggregate(cs):
438 for f in cs[2]:
438 for f in cs[2]:
439 ext = lower(f.extension)
439 ext = lower(f.extension)
440 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
440 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
441 if ext in code_stats:
441 if ext in code_stats:
442 code_stats[ext] += 1
442 code_stats[ext] += 1
443 else:
443 else:
444 code_stats[ext] = 1
444 code_stats[ext] = 1
445
445
446 map(aggregate, tip.walk('/'))
446 map(aggregate, tip.walk('/'))
447
447
448 return code_stats or {}
448 return code_stats or {}
General Comments 0
You need to be logged in to leave comments. Login now