##// END OF EJS Templates
fixed whoosh indexing from admin panel
marcink -
r685:87943675 beta
parent child Browse files
Show More
@@ -1,298 +1,299 b''
1 1 from celery.decorators import task
2 2
3 3 from operator import itemgetter
4 4 from pylons.i18n.translation import _
5 5 from rhodecode.lib.celerylib import run_task, locked_task
6 6 from rhodecode.lib.helpers import person
7 7 from rhodecode.lib.smtp_mailer import SmtpMailer
8 8 from rhodecode.lib.utils import OrderedDict
9 9 from time import mktime
10 10 import os
11 11 import traceback
12 12 from vcs.backends import get_repo
13 13 from rhodecode.model.hg import HgModel
14 14 try:
15 15 import json
16 16 except ImportError:
17 17 #python 2.5 compatibility
18 18 import simplejson as json
19 19
20 20 try:
21 21 from celeryconfig import PYLONS_CONFIG as config
22 22 celery_on = True
23 23 except ImportError:
24 24 #if celeryconfig is not present let's just load our pylons
25 25 #config instead
26 26 from pylons import config
27 27 celery_on = False
28 28
29 29
30 30 __all__ = ['whoosh_index', 'get_commits_stats',
31 31 'reset_user_password', 'send_email']
32 32
33 33 def get_session():
34 34 if celery_on:
35 35 from sqlalchemy import engine_from_config
36 36 from sqlalchemy.orm import sessionmaker, scoped_session
37 engine = engine_from_config(dict(config.items('app:main')), 'sqlalchemy.db1.')
37 engine = engine_from_config(dict(config.items('app:main')),
38 'sqlalchemy.db1.')
38 39 sa = scoped_session(sessionmaker(bind=engine))
39 40 else:
40 41 #If we don't use celery reuse our current application Session
41 42 from rhodecode.model.meta import Session
42 43 sa = Session()
43 44
44 45 return sa
45 46
46 47 @task
47 48 @locked_task
48 49 def whoosh_index(repo_location, full_index):
49 50 log = whoosh_index.get_logger()
50 51 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
51 index_location = ''
52 index_location = dict(config.items('app:main'))['index_dir']
52 53 WhooshIndexingDaemon(index_location=index_location,
53 54 repo_location=repo_location).run(full_index=full_index)
54 55
55 56 @task
56 57 @locked_task
57 58 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
58 59 from rhodecode.model.db import Statistics, Repository
59 60 log = get_commits_stats.get_logger()
60 61 author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty
61 62
62 63 commits_by_day_author_aggregate = {}
63 64 commits_by_day_aggregate = {}
64 65 repos_path = HgModel().repos_path
65 66 p = os.path.join(repos_path, repo_name)
66 67 repo = get_repo(p)
67 68
68 69 skip_date_limit = True
69 70 parse_limit = 250 #limit for single task changeset parsing optimal for
70 71 last_rev = 0
71 72 last_cs = None
72 73 timegetter = itemgetter('time')
73 74
74 75 sa = get_session()
75 76
76 77 dbrepo = sa.query(Repository)\
77 78 .filter(Repository.repo_name == repo_name).scalar()
78 79 cur_stats = sa.query(Statistics)\
79 80 .filter(Statistics.repository == dbrepo).scalar()
80 81 if cur_stats:
81 82 last_rev = cur_stats.stat_on_revision
82 83 if not repo.revisions:
83 84 return True
84 85
85 86 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
86 87 #pass silently without any work if we're not on first revision or current
87 88 #state of parsing revision(from db marker) is the last revision
88 89 return True
89 90
90 91 if cur_stats:
91 92 commits_by_day_aggregate = OrderedDict(
92 93 json.loads(
93 94 cur_stats.commit_activity_combined))
94 95 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
95 96
96 97 log.debug('starting parsing %s', parse_limit)
97 98 lmktime = mktime
98 99
99 100 for cnt, rev in enumerate(repo.revisions[last_rev:]):
100 101 last_cs = cs = repo.get_changeset(rev)
101 102 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
102 103 cs.date.timetuple()[2])
103 104 timetupple = [int(x) for x in k.split('-')]
104 105 timetupple.extend([0 for _ in xrange(6)])
105 106 k = lmktime(timetupple)
106 107 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
107 108 try:
108 109 l = [timegetter(x) for x in commits_by_day_author_aggregate\
109 110 [author_key_cleaner(cs.author)]['data']]
110 111 time_pos = l.index(k)
111 112 except ValueError:
112 113 time_pos = False
113 114
114 115 if time_pos >= 0 and time_pos is not False:
115 116
116 117 datadict = commits_by_day_author_aggregate\
117 118 [author_key_cleaner(cs.author)]['data'][time_pos]
118 119
119 120 datadict["commits"] += 1
120 121 datadict["added"] += len(cs.added)
121 122 datadict["changed"] += len(cs.changed)
122 123 datadict["removed"] += len(cs.removed)
123 124
124 125 else:
125 126 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
126 127
127 128 datadict = {"time":k,
128 129 "commits":1,
129 130 "added":len(cs.added),
130 131 "changed":len(cs.changed),
131 132 "removed":len(cs.removed),
132 133 }
133 134 commits_by_day_author_aggregate\
134 135 [author_key_cleaner(cs.author)]['data'].append(datadict)
135 136
136 137 else:
137 138 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
138 139 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
139 140 "label":author_key_cleaner(cs.author),
140 141 "data":[{"time":k,
141 142 "commits":1,
142 143 "added":len(cs.added),
143 144 "changed":len(cs.changed),
144 145 "removed":len(cs.removed),
145 146 }],
146 147 "schema":["commits"],
147 148 }
148 149
149 150 #gather all data by day
150 151 if commits_by_day_aggregate.has_key(k):
151 152 commits_by_day_aggregate[k] += 1
152 153 else:
153 154 commits_by_day_aggregate[k] = 1
154 155
155 156 if cnt >= parse_limit:
156 157 #don't fetch to much data since we can freeze application
157 158 break
158 159 overview_data = []
159 160 for k, v in commits_by_day_aggregate.items():
160 161 overview_data.append([k, v])
161 162 overview_data = sorted(overview_data, key=itemgetter(0))
162 163 if not commits_by_day_author_aggregate:
163 164 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
164 165 "label":author_key_cleaner(repo.contact),
165 166 "data":[0, 1],
166 167 "schema":["commits"],
167 168 }
168 169
169 170 stats = cur_stats if cur_stats else Statistics()
170 171 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
171 172 stats.commit_activity_combined = json.dumps(overview_data)
172 173
173 174 log.debug('last revison %s', last_rev)
174 175 leftovers = len(repo.revisions[last_rev:])
175 176 log.debug('revisions to parse %s', leftovers)
176 177
177 178 if last_rev == 0 or leftovers < parse_limit:
178 179 stats.languages = json.dumps(__get_codes_stats(repo_name))
179 180
180 181 stats.repository = dbrepo
181 182 stats.stat_on_revision = last_cs.revision
182 183
183 184 try:
184 185 sa.add(stats)
185 186 sa.commit()
186 187 except:
187 188 log.error(traceback.format_exc())
188 189 sa.rollback()
189 190 return False
190 191 if len(repo.revisions) > 1:
191 192 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
192 193
193 194 return True
194 195
195 196 @task
196 197 def reset_user_password(user_email):
197 198 log = reset_user_password.get_logger()
198 199 from rhodecode.lib import auth
199 200 from rhodecode.model.db import User
200 201
201 202 try:
202 203 try:
203 204 sa = get_session()
204 205 user = sa.query(User).filter(User.email == user_email).scalar()
205 206 new_passwd = auth.PasswordGenerator().gen_password(8,
206 207 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
207 208 if user:
208 209 user.password = auth.get_crypt_password(new_passwd)
209 210 sa.add(user)
210 211 sa.commit()
211 212 log.info('change password for %s', user_email)
212 213 if new_passwd is None:
213 214 raise Exception('unable to generate new password')
214 215
215 216 except:
216 217 log.error(traceback.format_exc())
217 218 sa.rollback()
218 219
219 220 run_task(send_email, user_email,
220 221 "Your new rhodecode password",
221 222 'Your new rhodecode password:%s' % (new_passwd))
222 223 log.info('send new password mail to %s', user_email)
223 224
224 225
225 226 except:
226 227 log.error('Failed to update user password')
227 228 log.error(traceback.format_exc())
228 229 return True
229 230
230 231 @task
231 232 def send_email(recipients, subject, body):
232 233 log = send_email.get_logger()
233 234 email_config = dict(config.items('DEFAULT'))
234 235 mail_from = email_config.get('app_email_from')
235 236 user = email_config.get('smtp_username')
236 237 passwd = email_config.get('smtp_password')
237 238 mail_server = email_config.get('smtp_server')
238 239 mail_port = email_config.get('smtp_port')
239 240 tls = email_config.get('smtp_use_tls')
240 241 ssl = False
241 242
242 243 try:
243 244 m = SmtpMailer(mail_from, user, passwd, mail_server,
244 245 mail_port, ssl, tls)
245 246 m.send(recipients, subject, body)
246 247 except:
247 248 log.error('Mail sending failed')
248 249 log.error(traceback.format_exc())
249 250 return False
250 251 return True
251 252
252 253 @task
253 254 def create_repo_fork(form_data, cur_user):
254 255 from rhodecode.model.repo import RepoModel
255 256 from vcs import get_backend
256 257 log = create_repo_fork.get_logger()
257 258 repo_model = RepoModel(get_session())
258 259 repo_model.create(form_data, cur_user, just_db=True, fork=True)
259 260 repo_name = form_data['repo_name']
260 261 repos_path = HgModel().repos_path
261 262 repo_path = os.path.join(repos_path, repo_name)
262 263 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
263 264 alias = form_data['repo_type']
264 265
265 266 log.info('creating repo fork %s as %s', repo_name, repo_path)
266 267 backend = get_backend(alias)
267 268 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
268 269
269 270 def __get_codes_stats(repo_name):
270 271 LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx',
271 272 'aspx', 'asx', 'axd', 'c', 'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el',
272 273 'erl', 'h', 'java', 'js', 'jsp', 'jspx', 'lisp', 'lua', 'm', 'mako', 'ml',
273 274 'pas', 'patch', 'php', 'php3', 'php4', 'phtml', 'pm', 'py', 'rb', 'rst',
274 275 's', 'sh', 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt', 'yaws']
275 276
276 277
277 278 repos_path = HgModel().repos_path
278 279 p = os.path.join(repos_path, repo_name)
279 280 repo = get_repo(p)
280 281 tip = repo.get_changeset()
281 282 code_stats = {}
282 283
283 284 def aggregate(cs):
284 285 for f in cs[2]:
285 286 k = f.mimetype
286 287 if f.extension in LANGUAGES_EXTENSIONS:
287 288 if code_stats.has_key(k):
288 289 code_stats[k] += 1
289 290 else:
290 291 code_stats[k] = 1
291 292
292 293 map(aggregate, tip.walk('/'))
293 294
294 295 return code_stats or {}
295 296
296 297
297 298
298 299
General Comments 0
You need to be logged in to leave comments. Login now