##// END OF EJS Templates
some small fixes to stats function
marcink -
r803:317ba4c8 beta
parent child Browse files
Show More
@@ -1,365 +1,363 b''
1 from celery.decorators import task
1 from celery.decorators import task
2
2
3 import os
3 import os
4 import traceback
4 import traceback
5 from time import mktime
5 from time import mktime
6 from operator import itemgetter
6 from operator import itemgetter
7
7
8 from pylons import config
8 from pylons import config
9 from pylons.i18n.translation import _
9 from pylons.i18n.translation import _
10
10
11 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
11 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
12 from rhodecode.lib.helpers import person
12 from rhodecode.lib.helpers import person
13 from rhodecode.lib.smtp_mailer import SmtpMailer
13 from rhodecode.lib.smtp_mailer import SmtpMailer
14 from rhodecode.lib.utils import OrderedDict, add_cache
14 from rhodecode.lib.utils import OrderedDict, add_cache
15 from rhodecode.model import init_model
15 from rhodecode.model import init_model
16 from rhodecode.model import meta
16 from rhodecode.model import meta
17 from rhodecode.model.db import RhodeCodeUi
17 from rhodecode.model.db import RhodeCodeUi
18
18
19 from vcs.backends import get_repo
19 from vcs.backends import get_repo
20
20
21 from sqlalchemy import engine_from_config
21 from sqlalchemy import engine_from_config
22
22
23 add_cache(config)
23 add_cache(config)
24
24
25 try:
25 try:
26 import json
26 import json
27 except ImportError:
27 except ImportError:
28 #python 2.5 compatibility
28 #python 2.5 compatibility
29 import simplejson as json
29 import simplejson as json
30
30
31 __all__ = ['whoosh_index', 'get_commits_stats',
31 __all__ = ['whoosh_index', 'get_commits_stats',
32 'reset_user_password', 'send_email']
32 'reset_user_password', 'send_email']
33
33
34 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
34 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
35
35
36 def get_session():
36 def get_session():
37 if CELERY_ON:
37 if CELERY_ON:
38 engine = engine_from_config(config, 'sqlalchemy.db1.')
38 engine = engine_from_config(config, 'sqlalchemy.db1.')
39 init_model(engine)
39 init_model(engine)
40 sa = meta.Session()
40 sa = meta.Session()
41 return sa
41 return sa
42
42
43 def get_repos_path():
43 def get_repos_path():
44 sa = get_session()
44 sa = get_session()
45 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
45 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
46 return q.ui_value
46 return q.ui_value
47
47
48 @task
48 @task
49 @locked_task
49 @locked_task
50 def whoosh_index(repo_location, full_index):
50 def whoosh_index(repo_location, full_index):
51 log = whoosh_index.get_logger()
51 log = whoosh_index.get_logger()
52 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
52 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
53 index_location = config['index_dir']
53 index_location = config['index_dir']
54 WhooshIndexingDaemon(index_location=index_location,
54 WhooshIndexingDaemon(index_location=index_location,
55 repo_location=repo_location, sa=get_session())\
55 repo_location=repo_location, sa=get_session())\
56 .run(full_index=full_index)
56 .run(full_index=full_index)
57
57
58 @task
58 @task
59 @locked_task
59 @locked_task
60 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
60 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
61 from rhodecode.model.db import Statistics, Repository
61 from rhodecode.model.db import Statistics, Repository
62 log = get_commits_stats.get_logger()
62 log = get_commits_stats.get_logger()
63
63
64 #for js data compatibilty
64 #for js data compatibilty
65 author_key_cleaner = lambda k: person(k).replace('"', "")
65 author_key_cleaner = lambda k: person(k).replace('"', "")
66
66
67 commits_by_day_author_aggregate = {}
67 commits_by_day_author_aggregate = {}
68 commits_by_day_aggregate = {}
68 commits_by_day_aggregate = {}
69 repos_path = get_repos_path()
69 repos_path = get_repos_path()
70 p = os.path.join(repos_path, repo_name)
70 p = os.path.join(repos_path, repo_name)
71 repo = get_repo(p)
71 repo = get_repo(p)
72
72
73 skip_date_limit = True
73 skip_date_limit = True
74 parse_limit = 250 #limit for single task changeset parsing optimal for
74 parse_limit = 250 #limit for single task changeset parsing optimal for
75 last_rev = 0
75 last_rev = 0
76 last_cs = None
76 last_cs = None
77 timegetter = itemgetter('time')
77 timegetter = itemgetter('time')
78
78
79 sa = get_session()
79 sa = get_session()
80
80
81 dbrepo = sa.query(Repository)\
81 dbrepo = sa.query(Repository)\
82 .filter(Repository.repo_name == repo_name).scalar()
82 .filter(Repository.repo_name == repo_name).scalar()
83 cur_stats = sa.query(Statistics)\
83 cur_stats = sa.query(Statistics)\
84 .filter(Statistics.repository == dbrepo).scalar()
84 .filter(Statistics.repository == dbrepo).scalar()
85 if cur_stats:
85 if cur_stats:
86 last_rev = cur_stats.stat_on_revision
86 last_rev = cur_stats.stat_on_revision
87 if not repo.revisions:
87 if not repo.revisions:
88 return True
88 return True
89
89
90 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
90 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
91 #pass silently without any work if we're not on first revision or
91 #pass silently without any work if we're not on first revision or
92 #current state of parsing revision(from db marker) is the last revision
92 #current state of parsing revision(from db marker) is the last revision
93 return True
93 return True
94
94
95 if cur_stats:
95 if cur_stats:
96 commits_by_day_aggregate = OrderedDict(
96 commits_by_day_aggregate = OrderedDict(
97 json.loads(
97 json.loads(
98 cur_stats.commit_activity_combined))
98 cur_stats.commit_activity_combined))
99 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
99 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
100
100
101 log.debug('starting parsing %s', parse_limit)
101 log.debug('starting parsing %s', parse_limit)
102 lmktime = mktime
102 lmktime = mktime
103
103
104 for cnt, rev in enumerate(repo.revisions[last_rev:]):
104 last_rev = last_rev + 1 if last_rev > 0 else last_rev
105 for rev in repo.revisions[last_rev:last_rev + parse_limit]:
105 last_cs = cs = repo.get_changeset(rev)
106 last_cs = cs = repo.get_changeset(rev)
106 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
107 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
107 cs.date.timetuple()[2])
108 cs.date.timetuple()[2])
108 timetupple = [int(x) for x in k.split('-')]
109 timetupple = [int(x) for x in k.split('-')]
109 timetupple.extend([0 for _ in xrange(6)])
110 timetupple.extend([0 for _ in xrange(6)])
110 k = lmktime(timetupple)
111 k = lmktime(timetupple)
111 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
112 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
112 try:
113 try:
113 l = [timegetter(x) for x in commits_by_day_author_aggregate\
114 l = [timegetter(x) for x in commits_by_day_author_aggregate\
114 [author_key_cleaner(cs.author)]['data']]
115 [author_key_cleaner(cs.author)]['data']]
115 time_pos = l.index(k)
116 time_pos = l.index(k)
116 except ValueError:
117 except ValueError:
117 time_pos = False
118 time_pos = False
118
119
119 if time_pos >= 0 and time_pos is not False:
120 if time_pos >= 0 and time_pos is not False:
120
121
121 datadict = commits_by_day_author_aggregate\
122 datadict = commits_by_day_author_aggregate\
122 [author_key_cleaner(cs.author)]['data'][time_pos]
123 [author_key_cleaner(cs.author)]['data'][time_pos]
123
124
124 datadict["commits"] += 1
125 datadict["commits"] += 1
125 datadict["added"] += len(cs.added)
126 datadict["added"] += len(cs.added)
126 datadict["changed"] += len(cs.changed)
127 datadict["changed"] += len(cs.changed)
127 datadict["removed"] += len(cs.removed)
128 datadict["removed"] += len(cs.removed)
128
129
129 else:
130 else:
130 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
131 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
131
132
132 datadict = {"time":k,
133 datadict = {"time":k,
133 "commits":1,
134 "commits":1,
134 "added":len(cs.added),
135 "added":len(cs.added),
135 "changed":len(cs.changed),
136 "changed":len(cs.changed),
136 "removed":len(cs.removed),
137 "removed":len(cs.removed),
137 }
138 }
138 commits_by_day_author_aggregate\
139 commits_by_day_author_aggregate\
139 [author_key_cleaner(cs.author)]['data'].append(datadict)
140 [author_key_cleaner(cs.author)]['data'].append(datadict)
140
141
141 else:
142 else:
142 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
143 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
143 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
144 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
144 "label":author_key_cleaner(cs.author),
145 "label":author_key_cleaner(cs.author),
145 "data":[{"time":k,
146 "data":[{"time":k,
146 "commits":1,
147 "commits":1,
147 "added":len(cs.added),
148 "added":len(cs.added),
148 "changed":len(cs.changed),
149 "changed":len(cs.changed),
149 "removed":len(cs.removed),
150 "removed":len(cs.removed),
150 }],
151 }],
151 "schema":["commits"],
152 "schema":["commits"],
152 }
153 }
153
154
154 #gather all data by day
155 #gather all data by day
155 if commits_by_day_aggregate.has_key(k):
156 if commits_by_day_aggregate.has_key(k):
156 commits_by_day_aggregate[k] += 1
157 commits_by_day_aggregate[k] += 1
157 else:
158 else:
158 commits_by_day_aggregate[k] = 1
159 commits_by_day_aggregate[k] = 1
159
160
160 if cnt >= parse_limit:
161 #don't fetch to much data since we can freeze application
162 break
163 overview_data = []
161 overview_data = []
164 for k, v in commits_by_day_aggregate.items():
162 for k, v in commits_by_day_aggregate.items():
165 overview_data.append([k, v])
163 overview_data.append([k, v])
166 overview_data = sorted(overview_data, key=itemgetter(0))
164 overview_data = sorted(overview_data, key=itemgetter(0))
167 if not commits_by_day_author_aggregate:
165 if not commits_by_day_author_aggregate:
168 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
166 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
169 "label":author_key_cleaner(repo.contact),
167 "label":author_key_cleaner(repo.contact),
170 "data":[0, 1],
168 "data":[0, 1],
171 "schema":["commits"],
169 "schema":["commits"],
172 }
170 }
173
171
174 stats = cur_stats if cur_stats else Statistics()
172 stats = cur_stats if cur_stats else Statistics()
175 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
173 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
176 stats.commit_activity_combined = json.dumps(overview_data)
174 stats.commit_activity_combined = json.dumps(overview_data)
177
175
178 log.debug('last revison %s', last_rev)
176 log.debug('last revison %s', last_rev)
179 leftovers = len(repo.revisions[last_rev:])
177 leftovers = len(repo.revisions[last_rev:])
180 log.debug('revisions to parse %s', leftovers)
178 log.debug('revisions to parse %s', leftovers)
181
179
182 if last_rev == 0 or leftovers < parse_limit:
180 if last_rev == 0 or leftovers < parse_limit:
183 stats.languages = json.dumps(__get_codes_stats(repo_name))
181 stats.languages = json.dumps(__get_codes_stats(repo_name))
184
182
185 stats.repository = dbrepo
183 stats.repository = dbrepo
186 stats.stat_on_revision = last_cs.revision
184 stats.stat_on_revision = last_cs.revision
187
185
188 try:
186 try:
189 sa.add(stats)
187 sa.add(stats)
190 sa.commit()
188 sa.commit()
191 except:
189 except:
192 log.error(traceback.format_exc())
190 log.error(traceback.format_exc())
193 sa.rollback()
191 sa.rollback()
194 return False
192 return False
195 if len(repo.revisions) > 1:
193 if len(repo.revisions) > 1:
196 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
194 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
197
195
198 return True
196 return True
199
197
200 @task
198 @task
201 def reset_user_password(user_email):
199 def reset_user_password(user_email):
202 log = reset_user_password.get_logger()
200 log = reset_user_password.get_logger()
203 from rhodecode.lib import auth
201 from rhodecode.lib import auth
204 from rhodecode.model.db import User
202 from rhodecode.model.db import User
205
203
206 try:
204 try:
207 try:
205 try:
208 sa = get_session()
206 sa = get_session()
209 user = sa.query(User).filter(User.email == user_email).scalar()
207 user = sa.query(User).filter(User.email == user_email).scalar()
210 new_passwd = auth.PasswordGenerator().gen_password(8,
208 new_passwd = auth.PasswordGenerator().gen_password(8,
211 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
209 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
212 if user:
210 if user:
213 user.password = auth.get_crypt_password(new_passwd)
211 user.password = auth.get_crypt_password(new_passwd)
214 sa.add(user)
212 sa.add(user)
215 sa.commit()
213 sa.commit()
216 log.info('change password for %s', user_email)
214 log.info('change password for %s', user_email)
217 if new_passwd is None:
215 if new_passwd is None:
218 raise Exception('unable to generate new password')
216 raise Exception('unable to generate new password')
219
217
220 except:
218 except:
221 log.error(traceback.format_exc())
219 log.error(traceback.format_exc())
222 sa.rollback()
220 sa.rollback()
223
221
224 run_task(send_email, user_email,
222 run_task(send_email, user_email,
225 "Your new rhodecode password",
223 "Your new rhodecode password",
226 'Your new rhodecode password:%s' % (new_passwd))
224 'Your new rhodecode password:%s' % (new_passwd))
227 log.info('send new password mail to %s', user_email)
225 log.info('send new password mail to %s', user_email)
228
226
229
227
230 except:
228 except:
231 log.error('Failed to update user password')
229 log.error('Failed to update user password')
232 log.error(traceback.format_exc())
230 log.error(traceback.format_exc())
233
231
234 return True
232 return True
235
233
236 @task
234 @task
237 def send_email(recipients, subject, body):
235 def send_email(recipients, subject, body):
238 """
236 """
239 Sends an email with defined parameters from the .ini files.
237 Sends an email with defined parameters from the .ini files.
240
238
241
239
242 :param recipients: list of recipients, it this is empty the defined email
240 :param recipients: list of recipients, it this is empty the defined email
243 address from field 'email_to' is used instead
241 address from field 'email_to' is used instead
244 :param subject: subject of the mail
242 :param subject: subject of the mail
245 :param body: body of the mail
243 :param body: body of the mail
246 """
244 """
247 log = send_email.get_logger()
245 log = send_email.get_logger()
248 email_config = config
246 email_config = config
249
247
250 if not recipients:
248 if not recipients:
251 recipients = [email_config.get('email_to')]
249 recipients = [email_config.get('email_to')]
252
250
253 mail_from = email_config.get('app_email_from')
251 mail_from = email_config.get('app_email_from')
254 user = email_config.get('smtp_username')
252 user = email_config.get('smtp_username')
255 passwd = email_config.get('smtp_password')
253 passwd = email_config.get('smtp_password')
256 mail_server = email_config.get('smtp_server')
254 mail_server = email_config.get('smtp_server')
257 mail_port = email_config.get('smtp_port')
255 mail_port = email_config.get('smtp_port')
258 tls = str2bool(email_config.get('smtp_use_tls'))
256 tls = str2bool(email_config.get('smtp_use_tls'))
259 ssl = str2bool(email_config.get('smtp_use_ssl'))
257 ssl = str2bool(email_config.get('smtp_use_ssl'))
260
258
261 try:
259 try:
262 m = SmtpMailer(mail_from, user, passwd, mail_server,
260 m = SmtpMailer(mail_from, user, passwd, mail_server,
263 mail_port, ssl, tls)
261 mail_port, ssl, tls)
264 m.send(recipients, subject, body)
262 m.send(recipients, subject, body)
265 except:
263 except:
266 log.error('Mail sending failed')
264 log.error('Mail sending failed')
267 log.error(traceback.format_exc())
265 log.error(traceback.format_exc())
268 return False
266 return False
269 return True
267 return True
270
268
271 @task
269 @task
272 def create_repo_fork(form_data, cur_user):
270 def create_repo_fork(form_data, cur_user):
273 from rhodecode.model.repo import RepoModel
271 from rhodecode.model.repo import RepoModel
274 from vcs import get_backend
272 from vcs import get_backend
275 log = create_repo_fork.get_logger()
273 log = create_repo_fork.get_logger()
276 repo_model = RepoModel(get_session())
274 repo_model = RepoModel(get_session())
277 repo_model.create(form_data, cur_user, just_db=True, fork=True)
275 repo_model.create(form_data, cur_user, just_db=True, fork=True)
278 repo_name = form_data['repo_name']
276 repo_name = form_data['repo_name']
279 repos_path = get_repos_path()
277 repos_path = get_repos_path()
280 repo_path = os.path.join(repos_path, repo_name)
278 repo_path = os.path.join(repos_path, repo_name)
281 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
279 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
282 alias = form_data['repo_type']
280 alias = form_data['repo_type']
283
281
284 log.info('creating repo fork %s as %s', repo_name, repo_path)
282 log.info('creating repo fork %s as %s', repo_name, repo_path)
285 backend = get_backend(alias)
283 backend = get_backend(alias)
286 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
284 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
287
285
288 def __get_codes_stats(repo_name):
286 def __get_codes_stats(repo_name):
289 LANGUAGES_EXTENSIONS_MAP = {'scm': 'Scheme', 'asmx': 'VbNetAspx', 'Rout':
287 LANGUAGES_EXTENSIONS_MAP = {'scm': 'Scheme', 'asmx': 'VbNetAspx', 'Rout':
290 'RConsole', 'rest': 'Rst', 'abap': 'ABAP', 'go': 'Go', 'phtml': 'HtmlPhp',
288 'RConsole', 'rest': 'Rst', 'abap': 'ABAP', 'go': 'Go', 'phtml': 'HtmlPhp',
291 'ns2': 'Newspeak', 'xml': 'EvoqueXml', 'sh-session': 'BashSession', 'ads':
289 'ns2': 'Newspeak', 'xml': 'EvoqueXml', 'sh-session': 'BashSession', 'ads':
292 'Ada', 'clj': 'Clojure', 'll': 'Llvm', 'ebuild': 'Bash', 'adb': 'Ada',
290 'Ada', 'clj': 'Clojure', 'll': 'Llvm', 'ebuild': 'Bash', 'adb': 'Ada',
293 'ada': 'Ada', 'c++-objdump': 'CppObjdump', 'aspx':
291 'ada': 'Ada', 'c++-objdump': 'CppObjdump', 'aspx':
294 'VbNetAspx', 'ksh': 'Bash', 'coffee': 'CoffeeScript', 'vert': 'GLShader',
292 'VbNetAspx', 'ksh': 'Bash', 'coffee': 'CoffeeScript', 'vert': 'GLShader',
295 'Makefile.*': 'Makefile', 'di': 'D', 'dpatch': 'DarcsPatch', 'rake':
293 'Makefile.*': 'Makefile', 'di': 'D', 'dpatch': 'DarcsPatch', 'rake':
296 'Ruby', 'moo': 'MOOCode', 'erl-sh': 'ErlangShell', 'geo': 'GLShader',
294 'Ruby', 'moo': 'MOOCode', 'erl-sh': 'ErlangShell', 'geo': 'GLShader',
297 'pov': 'Povray', 'bas': 'VbNet', 'bat': 'Batch', 'd': 'D', 'lisp':
295 'pov': 'Povray', 'bas': 'VbNet', 'bat': 'Batch', 'd': 'D', 'lisp':
298 'CommonLisp', 'h': 'C', 'rbx': 'Ruby', 'tcl': 'Tcl', 'c++': 'Cpp', 'md':
296 'CommonLisp', 'h': 'C', 'rbx': 'Ruby', 'tcl': 'Tcl', 'c++': 'Cpp', 'md':
299 'MiniD', '.vimrc': 'Vim', 'xsd': 'Xml', 'ml': 'Ocaml', 'el': 'CommonLisp',
297 'MiniD', '.vimrc': 'Vim', 'xsd': 'Xml', 'ml': 'Ocaml', 'el': 'CommonLisp',
300 'befunge': 'Befunge', 'xsl': 'Xslt', 'pyx': 'Cython', 'cfm':
298 'befunge': 'Befunge', 'xsl': 'Xslt', 'pyx': 'Cython', 'cfm':
301 'ColdfusionHtml', 'evoque': 'Evoque', 'cfg': 'Ini', 'htm': 'Html',
299 'ColdfusionHtml', 'evoque': 'Evoque', 'cfg': 'Ini', 'htm': 'Html',
302 'Makefile': 'Makefile', 'cfc': 'ColdfusionHtml', 'tex': 'Tex', 'cs':
300 'Makefile': 'Makefile', 'cfc': 'ColdfusionHtml', 'tex': 'Tex', 'cs':
303 'CSharp', 'mxml': 'Mxml', 'patch': 'Diff', 'apache.conf': 'ApacheConf',
301 'CSharp', 'mxml': 'Mxml', 'patch': 'Diff', 'apache.conf': 'ApacheConf',
304 'scala': 'Scala', 'applescript': 'AppleScript', 'GNUmakefile': 'Makefile',
302 'scala': 'Scala', 'applescript': 'AppleScript', 'GNUmakefile': 'Makefile',
305 'c-objdump': 'CObjdump', 'lua': 'Lua', 'apache2.conf': 'ApacheConf', 'rb':
303 'c-objdump': 'CObjdump', 'lua': 'Lua', 'apache2.conf': 'ApacheConf', 'rb':
306 'Ruby', 'gemspec': 'Ruby', 'rl': 'RagelObjectiveC', 'vala': 'Vala', 'tmpl':
304 'Ruby', 'gemspec': 'Ruby', 'rl': 'RagelObjectiveC', 'vala': 'Vala', 'tmpl':
307 'Cheetah', 'bf': 'Brainfuck', 'plt': 'Gnuplot', 'G': 'AntlrRuby', 'xslt':
305 'Cheetah', 'bf': 'Brainfuck', 'plt': 'Gnuplot', 'G': 'AntlrRuby', 'xslt':
308 'Xslt', 'flxh': 'Felix', 'asax': 'VbNetAspx', 'Rakefile': 'Ruby', 'S': 'S',
306 'Xslt', 'flxh': 'Felix', 'asax': 'VbNetAspx', 'Rakefile': 'Ruby', 'S': 'S',
309 'wsdl': 'Xml', 'js': 'Javascript', 'autodelegate': 'Myghty', 'properties':
307 'wsdl': 'Xml', 'js': 'Javascript', 'autodelegate': 'Myghty', 'properties':
310 'Ini', 'bash': 'Bash', 'c': 'C', 'g': 'AntlrRuby', 'r3': 'Rebol', 's':
308 'Ini', 'bash': 'Bash', 'c': 'C', 'g': 'AntlrRuby', 'r3': 'Rebol', 's':
311 'Gas', 'ashx': 'VbNetAspx', 'cxx': 'Cpp', 'boo': 'Boo', 'prolog': 'Prolog',
309 'Gas', 'ashx': 'VbNetAspx', 'cxx': 'Cpp', 'boo': 'Boo', 'prolog': 'Prolog',
312 'sqlite3-console': 'SqliteConsole', 'cl': 'CommonLisp', 'cc': 'Cpp', 'pot':
310 'sqlite3-console': 'SqliteConsole', 'cl': 'CommonLisp', 'cc': 'Cpp', 'pot':
313 'Gettext', 'vim': 'Vim', 'pxi': 'Cython', 'yaml': 'Yaml', 'SConstruct':
311 'Gettext', 'vim': 'Vim', 'pxi': 'Cython', 'yaml': 'Yaml', 'SConstruct':
314 'Python', 'diff': 'Diff', 'txt': 'Text', 'cw': 'Redcode', 'pxd': 'Cython',
312 'Python', 'diff': 'Diff', 'txt': 'Text', 'cw': 'Redcode', 'pxd': 'Cython',
315 'plot': 'Gnuplot', 'java': 'Java', 'hrl': 'Erlang', 'py': 'Python',
313 'plot': 'Gnuplot', 'java': 'Java', 'hrl': 'Erlang', 'py': 'Python',
316 'makefile': 'Makefile', 'squid.conf': 'SquidConf', 'asm': 'Nasm', 'toc':
314 'makefile': 'Makefile', 'squid.conf': 'SquidConf', 'asm': 'Nasm', 'toc':
317 'Tex', 'kid': 'Genshi', 'rhtml': 'Rhtml', 'po': 'Gettext', 'pl': 'Prolog',
315 'Tex', 'kid': 'Genshi', 'rhtml': 'Rhtml', 'po': 'Gettext', 'pl': 'Prolog',
318 'pm': 'Perl', 'hx': 'Haxe', 'ascx': 'VbNetAspx', 'ooc': 'Ooc', 'asy':
316 'pm': 'Perl', 'hx': 'Haxe', 'ascx': 'VbNetAspx', 'ooc': 'Ooc', 'asy':
319 'Asymptote', 'hs': 'Haskell', 'SConscript': 'Python', 'pytb':
317 'Asymptote', 'hs': 'Haskell', 'SConscript': 'Python', 'pytb':
320 'PythonTraceback', 'myt': 'Myghty', 'hh': 'Cpp', 'R': 'S', 'aux': 'Tex',
318 'PythonTraceback', 'myt': 'Myghty', 'hh': 'Cpp', 'R': 'S', 'aux': 'Tex',
321 'rst': 'Rst', 'cpp-objdump': 'CppObjdump', 'lgt': 'Logtalk', 'rss': 'Xml',
319 'rst': 'Rst', 'cpp-objdump': 'CppObjdump', 'lgt': 'Logtalk', 'rss': 'Xml',
322 'flx': 'Felix', 'b': 'Brainfuck', 'f': 'Fortran', 'rbw': 'Ruby',
320 'flx': 'Felix', 'b': 'Brainfuck', 'f': 'Fortran', 'rbw': 'Ruby',
323 '.htaccess': 'ApacheConf', 'cxx-objdump': 'CppObjdump', 'j': 'ObjectiveJ',
321 '.htaccess': 'ApacheConf', 'cxx-objdump': 'CppObjdump', 'j': 'ObjectiveJ',
324 'mll': 'Ocaml', 'yml': 'Yaml', 'mu': 'MuPAD', 'r': 'Rebol', 'ASM': 'Nasm',
322 'mll': 'Ocaml', 'yml': 'Yaml', 'mu': 'MuPAD', 'r': 'Rebol', 'ASM': 'Nasm',
325 'erl': 'Erlang', 'mly': 'Ocaml', 'mo': 'Modelica', 'def': 'Modula2', 'ini':
323 'erl': 'Erlang', 'mly': 'Ocaml', 'mo': 'Modelica', 'def': 'Modula2', 'ini':
326 'Ini', 'control': 'DebianControl', 'vb': 'VbNet', 'vapi': 'Vala', 'pro':
324 'Ini', 'control': 'DebianControl', 'vb': 'VbNet', 'vapi': 'Vala', 'pro':
327 'Prolog', 'spt': 'Cheetah', 'mli': 'Ocaml', 'as': 'ActionScript3', 'cmd':
325 'Prolog', 'spt': 'Cheetah', 'mli': 'Ocaml', 'as': 'ActionScript3', 'cmd':
328 'Batch', 'cpp': 'Cpp', 'io': 'Io', 'tac': 'Python', 'haml': 'Haml', 'rkt':
326 'Batch', 'cpp': 'Cpp', 'io': 'Io', 'tac': 'Python', 'haml': 'Haml', 'rkt':
329 'Racket', 'st':'Smalltalk', 'inc': 'Povray', 'pas': 'Delphi', 'cmake':
327 'Racket', 'st':'Smalltalk', 'inc': 'Povray', 'pas': 'Delphi', 'cmake':
330 'CMake', 'csh':'Tcsh', 'hpp': 'Cpp', 'feature': 'Gherkin', 'html': 'Html',
328 'CMake', 'csh':'Tcsh', 'hpp': 'Cpp', 'feature': 'Gherkin', 'html': 'Html',
331 'php':'Php', 'php3':'Php', 'php4':'Php', 'php5':'Php', 'xhtml': 'Html',
329 'php':'Php', 'php3':'Php', 'php4':'Php', 'php5':'Php', 'xhtml': 'Html',
332 'hxx': 'Cpp', 'eclass': 'Bash', 'css': 'Css',
330 'hxx': 'Cpp', 'eclass': 'Bash', 'css': 'Css',
333 'frag': 'GLShader', 'd-objdump': 'DObjdump', 'weechatlog': 'IrcLogs',
331 'frag': 'GLShader', 'd-objdump': 'DObjdump', 'weechatlog': 'IrcLogs',
334 'tcsh': 'Tcsh', 'objdump': 'Objdump', 'pyw': 'Python', 'h++': 'Cpp',
332 'tcsh': 'Tcsh', 'objdump': 'Objdump', 'pyw': 'Python', 'h++': 'Cpp',
335 'py3tb': 'Python3Traceback', 'jsp': 'Jsp', 'sql': 'Sql', 'mak': 'Makefile',
333 'py3tb': 'Python3Traceback', 'jsp': 'Jsp', 'sql': 'Sql', 'mak': 'Makefile',
336 'php': 'Php', 'mao': 'Mako', 'man': 'Groff', 'dylan': 'Dylan', 'sass':
334 'php': 'Php', 'mao': 'Mako', 'man': 'Groff', 'dylan': 'Dylan', 'sass':
337 'Sass', 'cfml': 'ColdfusionHtml', 'darcspatch': 'DarcsPatch', 'tpl':
335 'Sass', 'cfml': 'ColdfusionHtml', 'darcspatch': 'DarcsPatch', 'tpl':
338 'Smarty', 'm': 'ObjectiveC', 'f90': 'Fortran', 'mod': 'Modula2', 'sh':
336 'Smarty', 'm': 'ObjectiveC', 'f90': 'Fortran', 'mod': 'Modula2', 'sh':
339 'Bash', 'lhs': 'LiterateHaskell', 'sources.list': 'SourcesList', 'axd':
337 'Bash', 'lhs': 'LiterateHaskell', 'sources.list': 'SourcesList', 'axd':
340 'VbNetAspx', 'sc': 'Python'}
338 'VbNetAspx', 'sc': 'Python'}
341
339
342 repos_path = get_repos_path()
340 repos_path = get_repos_path()
343 p = os.path.join(repos_path, repo_name)
341 p = os.path.join(repos_path, repo_name)
344 repo = get_repo(p)
342 repo = get_repo(p)
345 tip = repo.get_changeset()
343 tip = repo.get_changeset()
346 code_stats = {}
344 code_stats = {}
347
345
348 def aggregate(cs):
346 def aggregate(cs):
349 for f in cs[2]:
347 for f in cs[2]:
350 ext = f.extension
348 ext = f.extension
351 key = LANGUAGES_EXTENSIONS_MAP.get(ext, ext)
349 key = LANGUAGES_EXTENSIONS_MAP.get(ext, ext)
352 key = key or ext
350 key = key or ext
353 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
351 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
354 if code_stats.has_key(key):
352 if code_stats.has_key(key):
355 code_stats[key] += 1
353 code_stats[key] += 1
356 else:
354 else:
357 code_stats[key] = 1
355 code_stats[key] = 1
358
356
359 map(aggregate, tip.walk('/'))
357 map(aggregate, tip.walk('/'))
360
358
361 return code_stats or {}
359 return code_stats or {}
362
360
363
361
364
362
365
363
General Comments 0
You need to be logged in to leave comments. Login now