##// END OF EJS Templates
Added uri encoding to the username so that usernames with '@' in them (such as email address/users from LDAP) will...
philip.j@hostdime.com -
r3048:3f0fe158 beta
parent child Browse files
Show More
@@ -1,249 +1,249 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.summary
3 rhodecode.controllers.summary
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Summary controller for Rhodecode
6 Summary controller for Rhodecode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 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 traceback
26 import traceback
27 import calendar
27 import calendar
28 import logging
28 import logging
29 import urllib
29 import urllib
30 from time import mktime
30 from time import mktime
31 from datetime import timedelta, date
31 from datetime import timedelta, date
32 from urlparse import urlparse
32 from urlparse import urlparse
33 from rhodecode.lib.compat import product
33 from rhodecode.lib.compat import product
34
34
35 from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \
35 from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \
36 NodeDoesNotExistError
36 NodeDoesNotExistError
37
37
38 from pylons import tmpl_context as c, request, url, config
38 from pylons import tmpl_context as c, request, url, config
39 from pylons.i18n.translation import _
39 from pylons.i18n.translation import _
40
40
41 from beaker.cache import cache_region, region_invalidate
41 from beaker.cache import cache_region, region_invalidate
42
42
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
44 from rhodecode.model.db import Statistics, CacheInvalidation
44 from rhodecode.model.db import Statistics, CacheInvalidation
45 from rhodecode.lib.utils2 import safe_unicode
45 from rhodecode.lib.utils2 import safe_unicode
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
47 from rhodecode.lib.base import BaseRepoController, render
47 from rhodecode.lib.base import BaseRepoController, render
48 from rhodecode.lib.vcs.backends.base import EmptyChangeset
48 from rhodecode.lib.vcs.backends.base import EmptyChangeset
49 from rhodecode.lib.markup_renderer import MarkupRenderer
49 from rhodecode.lib.markup_renderer import MarkupRenderer
50 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib import run_task
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
52 from rhodecode.lib.helpers import RepoPage
52 from rhodecode.lib.helpers import RepoPage
53 from rhodecode.lib.compat import json, OrderedDict
53 from rhodecode.lib.compat import json, OrderedDict
54 from rhodecode.lib.vcs.nodes import FileNode
54 from rhodecode.lib.vcs.nodes import FileNode
55
55
56 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
57
57
58 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
58 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
59 sorted(list(product(ALL_READMES, ALL_EXTS)),
59 sorted(list(product(ALL_READMES, ALL_EXTS)),
60 key=lambda y:y[0][1] + y[1][1])]
60 key=lambda y:y[0][1] + y[1][1])]
61
61
62
62
63 class SummaryController(BaseRepoController):
63 class SummaryController(BaseRepoController):
64
64
65 @LoginRequired()
65 @LoginRequired()
66 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
66 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
67 'repository.admin')
67 'repository.admin')
68 def __before__(self):
68 def __before__(self):
69 super(SummaryController, self).__before__()
69 super(SummaryController, self).__before__()
70
70
71 def index(self, repo_name):
71 def index(self, repo_name):
72 c.dbrepo = dbrepo = c.rhodecode_db_repo
72 c.dbrepo = dbrepo = c.rhodecode_db_repo
73 c.following = self.scm_model.is_following_repo(repo_name,
73 c.following = self.scm_model.is_following_repo(repo_name,
74 self.rhodecode_user.user_id)
74 self.rhodecode_user.user_id)
75
75
76 def url_generator(**kw):
76 def url_generator(**kw):
77 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
77 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
78
78
79 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
79 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
80 items_per_page=10, url=url_generator)
80 items_per_page=10, url=url_generator)
81 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
81 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
82 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
82 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
83
83
84 if self.rhodecode_user.username == 'default':
84 if self.rhodecode_user.username == 'default':
85 # for default(anonymous) user we don't need to pass credentials
85 # for default(anonymous) user we don't need to pass credentials
86 username = ''
86 username = ''
87 password = ''
87 password = ''
88 else:
88 else:
89 username = str(self.rhodecode_user.username)
89 username = str(self.rhodecode_user.username)
90 password = '@'
90 password = '@'
91
91
92 parsed_url = urlparse(url.current(qualified=True))
92 parsed_url = urlparse(url.current(qualified=True))
93
93
94 default_clone_uri = '{scheme}://{user}{pass}{netloc}{path}'
94 default_clone_uri = '{scheme}://{user}{pass}{netloc}{path}'
95
95
96 uri_tmpl = config.get('clone_uri', default_clone_uri)
96 uri_tmpl = config.get('clone_uri', default_clone_uri)
97 uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s')
97 uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s')
98 decoded_path = safe_unicode(urllib.unquote(parsed_url.path))
98 decoded_path = safe_unicode(urllib.unquote(parsed_url.path))
99 uri_dict = {
99 uri_dict = {
100 'user': username,
100 'user': urllib.quote(username),
101 'pass': password,
101 'pass': password,
102 'scheme': parsed_url.scheme,
102 'scheme': parsed_url.scheme,
103 'netloc': parsed_url.netloc,
103 'netloc': parsed_url.netloc,
104 'path': decoded_path
104 'path': decoded_path
105 }
105 }
106
106
107 uri = uri_tmpl % uri_dict
107 uri = uri_tmpl % uri_dict
108 # generate another clone url by id
108 # generate another clone url by id
109 uri_dict.update(
109 uri_dict.update(
110 {'path': decoded_path.replace(repo_name, '_%s' % c.dbrepo.repo_id)}
110 {'path': decoded_path.replace(repo_name, '_%s' % c.dbrepo.repo_id)}
111 )
111 )
112 uri_id = uri_tmpl % uri_dict
112 uri_id = uri_tmpl % uri_dict
113
113
114 c.clone_repo_url = uri
114 c.clone_repo_url = uri
115 c.clone_repo_url_id = uri_id
115 c.clone_repo_url_id = uri_id
116 c.repo_tags = OrderedDict()
116 c.repo_tags = OrderedDict()
117 for name, hash_ in c.rhodecode_repo.tags.items()[:10]:
117 for name, hash_ in c.rhodecode_repo.tags.items()[:10]:
118 try:
118 try:
119 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash_)
119 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash_)
120 except ChangesetError:
120 except ChangesetError:
121 c.repo_tags[name] = EmptyChangeset(hash_)
121 c.repo_tags[name] = EmptyChangeset(hash_)
122
122
123 c.repo_branches = OrderedDict()
123 c.repo_branches = OrderedDict()
124 for name, hash_ in c.rhodecode_repo.branches.items()[:10]:
124 for name, hash_ in c.rhodecode_repo.branches.items()[:10]:
125 try:
125 try:
126 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash_)
126 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash_)
127 except ChangesetError:
127 except ChangesetError:
128 c.repo_branches[name] = EmptyChangeset(hash_)
128 c.repo_branches[name] = EmptyChangeset(hash_)
129
129
130 td = date.today() + timedelta(days=1)
130 td = date.today() + timedelta(days=1)
131 td_1m = td - timedelta(days=calendar.mdays[td.month])
131 td_1m = td - timedelta(days=calendar.mdays[td.month])
132 td_1y = td - timedelta(days=365)
132 td_1y = td - timedelta(days=365)
133
133
134 ts_min_m = mktime(td_1m.timetuple())
134 ts_min_m = mktime(td_1m.timetuple())
135 ts_min_y = mktime(td_1y.timetuple())
135 ts_min_y = mktime(td_1y.timetuple())
136 ts_max_y = mktime(td.timetuple())
136 ts_max_y = mktime(td.timetuple())
137
137
138 if dbrepo.enable_statistics:
138 if dbrepo.enable_statistics:
139 c.show_stats = True
139 c.show_stats = True
140 c.no_data_msg = _('No data loaded yet')
140 c.no_data_msg = _('No data loaded yet')
141 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
141 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
142 else:
142 else:
143 c.show_stats = False
143 c.show_stats = False
144 c.no_data_msg = _('Statistics are disabled for this repository')
144 c.no_data_msg = _('Statistics are disabled for this repository')
145 c.ts_min = ts_min_m
145 c.ts_min = ts_min_m
146 c.ts_max = ts_max_y
146 c.ts_max = ts_max_y
147
147
148 stats = self.sa.query(Statistics)\
148 stats = self.sa.query(Statistics)\
149 .filter(Statistics.repository == dbrepo)\
149 .filter(Statistics.repository == dbrepo)\
150 .scalar()
150 .scalar()
151
151
152 c.stats_percentage = 0
152 c.stats_percentage = 0
153
153
154 if stats and stats.languages:
154 if stats and stats.languages:
155 c.no_data = False is dbrepo.enable_statistics
155 c.no_data = False is dbrepo.enable_statistics
156 lang_stats_d = json.loads(stats.languages)
156 lang_stats_d = json.loads(stats.languages)
157 c.commit_data = stats.commit_activity
157 c.commit_data = stats.commit_activity
158 c.overview_data = stats.commit_activity_combined
158 c.overview_data = stats.commit_activity_combined
159
159
160 lang_stats = ((x, {"count": y,
160 lang_stats = ((x, {"count": y,
161 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
161 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
162 for x, y in lang_stats_d.items())
162 for x, y in lang_stats_d.items())
163
163
164 c.trending_languages = json.dumps(
164 c.trending_languages = json.dumps(
165 sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
165 sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
166 )
166 )
167 last_rev = stats.stat_on_revision + 1
167 last_rev = stats.stat_on_revision + 1
168 c.repo_last_rev = c.rhodecode_repo.count()\
168 c.repo_last_rev = c.rhodecode_repo.count()\
169 if c.rhodecode_repo.revisions else 0
169 if c.rhodecode_repo.revisions else 0
170 if last_rev == 0 or c.repo_last_rev == 0:
170 if last_rev == 0 or c.repo_last_rev == 0:
171 pass
171 pass
172 else:
172 else:
173 c.stats_percentage = '%.2f' % ((float((last_rev)) /
173 c.stats_percentage = '%.2f' % ((float((last_rev)) /
174 c.repo_last_rev) * 100)
174 c.repo_last_rev) * 100)
175 else:
175 else:
176 c.commit_data = json.dumps({})
176 c.commit_data = json.dumps({})
177 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
177 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
178 c.trending_languages = json.dumps({})
178 c.trending_languages = json.dumps({})
179 c.no_data = True
179 c.no_data = True
180
180
181 c.enable_downloads = dbrepo.enable_downloads
181 c.enable_downloads = dbrepo.enable_downloads
182 if c.enable_downloads:
182 if c.enable_downloads:
183 c.download_options = self._get_download_links(c.rhodecode_repo)
183 c.download_options = self._get_download_links(c.rhodecode_repo)
184
184
185 c.readme_data, c.readme_file = \
185 c.readme_data, c.readme_file = \
186 self.__get_readme_data(c.rhodecode_db_repo)
186 self.__get_readme_data(c.rhodecode_db_repo)
187 return render('summary/summary.html')
187 return render('summary/summary.html')
188
188
189 def __get_readme_data(self, db_repo):
189 def __get_readme_data(self, db_repo):
190 repo_name = db_repo.repo_name
190 repo_name = db_repo.repo_name
191
191
192 @cache_region('long_term')
192 @cache_region('long_term')
193 def _get_readme_from_cache(key):
193 def _get_readme_from_cache(key):
194 readme_data = None
194 readme_data = None
195 readme_file = None
195 readme_file = None
196 log.debug('Looking for README file')
196 log.debug('Looking for README file')
197 try:
197 try:
198 # get's the landing revision! or tip if fails
198 # get's the landing revision! or tip if fails
199 cs = db_repo.get_landing_changeset()
199 cs = db_repo.get_landing_changeset()
200 if isinstance(cs, EmptyChangeset):
200 if isinstance(cs, EmptyChangeset):
201 raise EmptyRepositoryError()
201 raise EmptyRepositoryError()
202 renderer = MarkupRenderer()
202 renderer = MarkupRenderer()
203 for f in README_FILES:
203 for f in README_FILES:
204 try:
204 try:
205 readme = cs.get_node(f)
205 readme = cs.get_node(f)
206 if not isinstance(readme, FileNode):
206 if not isinstance(readme, FileNode):
207 continue
207 continue
208 readme_file = f
208 readme_file = f
209 log.debug('Found README file `%s` rendering...' %
209 log.debug('Found README file `%s` rendering...' %
210 readme_file)
210 readme_file)
211 readme_data = renderer.render(readme.content, f)
211 readme_data = renderer.render(readme.content, f)
212 break
212 break
213 except NodeDoesNotExistError:
213 except NodeDoesNotExistError:
214 continue
214 continue
215 except ChangesetError:
215 except ChangesetError:
216 log.error(traceback.format_exc())
216 log.error(traceback.format_exc())
217 pass
217 pass
218 except EmptyRepositoryError:
218 except EmptyRepositoryError:
219 pass
219 pass
220 except Exception:
220 except Exception:
221 log.error(traceback.format_exc())
221 log.error(traceback.format_exc())
222
222
223 return readme_data, readme_file
223 return readme_data, readme_file
224
224
225 key = repo_name + '_README'
225 key = repo_name + '_README'
226 inv = CacheInvalidation.invalidate(key)
226 inv = CacheInvalidation.invalidate(key)
227 if inv is not None:
227 if inv is not None:
228 region_invalidate(_get_readme_from_cache, None, key)
228 region_invalidate(_get_readme_from_cache, None, key)
229 CacheInvalidation.set_valid(inv.cache_key)
229 CacheInvalidation.set_valid(inv.cache_key)
230 return _get_readme_from_cache(key)
230 return _get_readme_from_cache(key)
231
231
232 def _get_download_links(self, repo):
232 def _get_download_links(self, repo):
233
233
234 download_l = []
234 download_l = []
235
235
236 branches_group = ([], _("Branches"))
236 branches_group = ([], _("Branches"))
237 tags_group = ([], _("Tags"))
237 tags_group = ([], _("Tags"))
238
238
239 for name, chs in c.rhodecode_repo.branches.items():
239 for name, chs in c.rhodecode_repo.branches.items():
240 #chs = chs.split(':')[-1]
240 #chs = chs.split(':')[-1]
241 branches_group[0].append((chs, name),)
241 branches_group[0].append((chs, name),)
242 download_l.append(branches_group)
242 download_l.append(branches_group)
243
243
244 for name, chs in c.rhodecode_repo.tags.items():
244 for name, chs in c.rhodecode_repo.tags.items():
245 #chs = chs.split(':')[-1]
245 #chs = chs.split(':')[-1]
246 tags_group[0].append((chs, name),)
246 tags_group[0].append((chs, name),)
247 download_l.append(tags_group)
247 download_l.append(tags_group)
248
248
249 return download_l
249 return download_l
General Comments 0
You need to be logged in to leave comments. Login now