##// END OF EJS Templates
summary: fixed 500 errors on loading just summary commits and missing clone_url set....
ergo -
r3545:b36b008a default
parent child Browse files
Show More
@@ -1,391 +1,393 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import string
23 23 import rhodecode
24 24
25 25 from pyramid.view import view_config
26 26
27 27 from rhodecode.lib.view_utils import get_format_ref_id
28 28 from rhodecode.apps._base import RepoAppView
29 29 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
30 30 from rhodecode.lib import helpers as h, rc_cache
31 31 from rhodecode.lib.utils2 import safe_str, safe_int
32 32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 33 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
34 34 from rhodecode.lib.ext_json import json
35 35 from rhodecode.lib.vcs.backends.base import EmptyCommit
36 36 from rhodecode.lib.vcs.exceptions import (
37 37 CommitError, EmptyRepositoryError, CommitDoesNotExistError)
38 38 from rhodecode.model.db import Statistics, CacheKey, User
39 39 from rhodecode.model.meta import Session
40 40 from rhodecode.model.repo import ReadmeFinder
41 41 from rhodecode.model.scm import ScmModel
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 class RepoSummaryView(RepoAppView):
47 47
48 48 def load_default_context(self):
49 49 c = self._get_local_tmpl_context(include_app_defaults=True)
50 50 c.rhodecode_repo = None
51 51 if not c.repository_requirements_missing:
52 52 c.rhodecode_repo = self.rhodecode_vcs_repo
53 53 return c
54 54
55 55 def _get_readme_data(self, db_repo, renderer_type):
56 56
57 57 log.debug('Looking for README file')
58 58
59 59 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
60 60 db_repo.repo_id, CacheKey.CACHE_TYPE_README)
61 61 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
62 62 repo_id=self.db_repo.repo_id)
63 63 region = rc_cache.get_or_create_region('cache_repo_longterm', cache_namespace_uid)
64 64
65 65 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid)
66 66 def generate_repo_readme(repo_id, _repo_name, _renderer_type):
67 67 readme_data = None
68 68 readme_node = None
69 69 readme_filename = None
70 70 commit = self._get_landing_commit_or_none(db_repo)
71 71 if commit:
72 72 log.debug("Searching for a README file.")
73 73 readme_node = ReadmeFinder(_renderer_type).search(commit)
74 74 if readme_node:
75 75 relative_urls = {
76 76 'raw': h.route_path(
77 77 'repo_file_raw', repo_name=_repo_name,
78 78 commit_id=commit.raw_id, f_path=readme_node.path),
79 79 'standard': h.route_path(
80 80 'repo_files', repo_name=_repo_name,
81 81 commit_id=commit.raw_id, f_path=readme_node.path),
82 82 }
83 83 readme_data = self._render_readme_or_none(
84 84 commit, readme_node, relative_urls)
85 85 readme_filename = readme_node.path
86 86 return readme_data, readme_filename
87 87
88 88 inv_context_manager = rc_cache.InvalidationContext(
89 89 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
90 90 with inv_context_manager as invalidation_context:
91 91 args = (db_repo.repo_id, db_repo.repo_name, renderer_type,)
92 92 # re-compute and store cache if we get invalidate signal
93 93 if invalidation_context.should_invalidate():
94 94 instance = generate_repo_readme.refresh(*args)
95 95 else:
96 96 instance = generate_repo_readme(*args)
97 97
98 98 log.debug(
99 99 'Repo readme generated and computed in %.3fs',
100 100 inv_context_manager.compute_time)
101 101 return instance
102 102
103 103 def _get_landing_commit_or_none(self, db_repo):
104 104 log.debug("Getting the landing commit.")
105 105 try:
106 106 commit = db_repo.get_landing_commit()
107 107 if not isinstance(commit, EmptyCommit):
108 108 return commit
109 109 else:
110 110 log.debug("Repository is empty, no README to render.")
111 111 except CommitError:
112 112 log.exception(
113 113 "Problem getting commit when trying to render the README.")
114 114
115 115 def _render_readme_or_none(self, commit, readme_node, relative_urls):
116 116 log.debug(
117 117 'Found README file `%s` rendering...', readme_node.path)
118 118 renderer = MarkupRenderer()
119 119 try:
120 120 html_source = renderer.render(
121 121 readme_node.content, filename=readme_node.path)
122 122 if relative_urls:
123 123 return relative_links(html_source, relative_urls)
124 124 return html_source
125 125 except Exception:
126 126 log.exception(
127 127 "Exception while trying to render the README")
128 128
129 129 def _load_commits_context(self, c):
130 130 p = safe_int(self.request.GET.get('page'), 1)
131 131 size = safe_int(self.request.GET.get('size'), 10)
132 132
133 133 def url_generator(**kw):
134 134 query_params = {
135 135 'size': size
136 136 }
137 137 query_params.update(kw)
138 138 return h.route_path(
139 139 'repo_summary_commits',
140 140 repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
141 141
142 142 pre_load = ['author', 'branch', 'date', 'message']
143 143 try:
144 144 collection = self.rhodecode_vcs_repo.get_commits(
145 145 pre_load=pre_load, translate_tags=False)
146 146 except EmptyRepositoryError:
147 147 collection = self.rhodecode_vcs_repo
148 148
149 149 c.repo_commits = h.RepoPage(
150 150 collection, page=p, items_per_page=size, url=url_generator)
151 151 page_ids = [x.raw_id for x in c.repo_commits]
152 152 c.comments = self.db_repo.get_comments(page_ids)
153 153 c.statuses = self.db_repo.statuses(page_ids)
154 154
155 def _prepare_and_set_clone_url(self, c):
156 username = ''
157 if self._rhodecode_user.username != User.DEFAULT_USER:
158 username = safe_str(self._rhodecode_user.username)
159
160 _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl
161 _def_clone_uri_ssh = c.clone_uri_ssh_tmpl
162
163 if '{repo}' in _def_clone_uri:
164 _def_clone_uri_id = _def_clone_uri.replace('{repo}', '_{repoid}')
165 elif '{repoid}' in _def_clone_uri:
166 _def_clone_uri_id = _def_clone_uri.replace('_{repoid}', '{repo}')
167
168 c.clone_repo_url = self.db_repo.clone_url(
169 user=username, uri_tmpl=_def_clone_uri)
170 c.clone_repo_url_id = self.db_repo.clone_url(
171 user=username, uri_tmpl=_def_clone_uri_id)
172 c.clone_repo_url_ssh = self.db_repo.clone_url(
173 uri_tmpl=_def_clone_uri_ssh, ssh=True)
174
155 175 @LoginRequired()
156 176 @HasRepoPermissionAnyDecorator(
157 177 'repository.read', 'repository.write', 'repository.admin')
158 178 @view_config(
159 179 route_name='repo_summary_commits', request_method='GET',
160 180 renderer='rhodecode:templates/summary/summary_commits.mako')
161 181 def summary_commits(self):
162 182 c = self.load_default_context()
183 self._prepare_and_set_clone_url(c)
163 184 self._load_commits_context(c)
164 185 return self._get_template_context(c)
165 186
166 187 @LoginRequired()
167 188 @HasRepoPermissionAnyDecorator(
168 189 'repository.read', 'repository.write', 'repository.admin')
169 190 @view_config(
170 191 route_name='repo_summary', request_method='GET',
171 192 renderer='rhodecode:templates/summary/summary.mako')
172 193 @view_config(
173 194 route_name='repo_summary_slash', request_method='GET',
174 195 renderer='rhodecode:templates/summary/summary.mako')
175 196 @view_config(
176 197 route_name='repo_summary_explicit', request_method='GET',
177 198 renderer='rhodecode:templates/summary/summary.mako')
178 199 def summary(self):
179 200 c = self.load_default_context()
180 201
181 202 # Prepare the clone URL
182 username = ''
183 if self._rhodecode_user.username != User.DEFAULT_USER:
184 username = safe_str(self._rhodecode_user.username)
185
186 _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl
187 _def_clone_uri_ssh = c.clone_uri_ssh_tmpl
188
189 if '{repo}' in _def_clone_uri:
190 _def_clone_uri_id = _def_clone_uri.replace(
191 '{repo}', '_{repoid}')
192 elif '{repoid}' in _def_clone_uri:
193 _def_clone_uri_id = _def_clone_uri.replace(
194 '_{repoid}', '{repo}')
195
196 c.clone_repo_url = self.db_repo.clone_url(
197 user=username, uri_tmpl=_def_clone_uri)
198 c.clone_repo_url_id = self.db_repo.clone_url(
199 user=username, uri_tmpl=_def_clone_uri_id)
200 c.clone_repo_url_ssh = self.db_repo.clone_url(
201 uri_tmpl=_def_clone_uri_ssh, ssh=True)
203 self._prepare_and_set_clone_url(c)
202 204
203 205 # If enabled, get statistics data
204 206
205 207 c.show_stats = bool(self.db_repo.enable_statistics)
206 208
207 209 stats = Session().query(Statistics) \
208 210 .filter(Statistics.repository == self.db_repo) \
209 211 .scalar()
210 212
211 213 c.stats_percentage = 0
212 214
213 215 if stats and stats.languages:
214 216 c.no_data = False is self.db_repo.enable_statistics
215 217 lang_stats_d = json.loads(stats.languages)
216 218
217 219 # Sort first by decreasing count and second by the file extension,
218 220 # so we have a consistent output.
219 221 lang_stats_items = sorted(lang_stats_d.iteritems(),
220 222 key=lambda k: (-k[1], k[0]))[:10]
221 223 lang_stats = [(x, {"count": y,
222 224 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
223 225 for x, y in lang_stats_items]
224 226
225 227 c.trending_languages = json.dumps(lang_stats)
226 228 else:
227 229 c.no_data = True
228 230 c.trending_languages = json.dumps({})
229 231
230 232 scm_model = ScmModel()
231 233 c.enable_downloads = self.db_repo.enable_downloads
232 234 c.repository_followers = scm_model.get_followers(self.db_repo)
233 235 c.repository_forks = scm_model.get_forks(self.db_repo)
234 236 c.repository_is_user_following = scm_model.is_following_repo(
235 237 self.db_repo_name, self._rhodecode_user.user_id)
236 238
237 239 # first interaction with the VCS instance after here...
238 240 if c.repository_requirements_missing:
239 241 self.request.override_renderer = \
240 242 'rhodecode:templates/summary/missing_requirements.mako'
241 243 return self._get_template_context(c)
242 244
243 245 c.readme_data, c.readme_file = \
244 246 self._get_readme_data(self.db_repo, c.visual.default_renderer)
245 247
246 248 # loads the summary commits template context
247 249 self._load_commits_context(c)
248 250
249 251 return self._get_template_context(c)
250 252
251 253 def get_request_commit_id(self):
252 254 return self.request.matchdict['commit_id']
253 255
254 256 @LoginRequired()
255 257 @HasRepoPermissionAnyDecorator(
256 258 'repository.read', 'repository.write', 'repository.admin')
257 259 @view_config(
258 260 route_name='repo_stats', request_method='GET',
259 261 renderer='json_ext')
260 262 def repo_stats(self):
261 263 commit_id = self.get_request_commit_id()
262 264 show_stats = bool(self.db_repo.enable_statistics)
263 265 repo_id = self.db_repo.repo_id
264 266
265 267 cache_seconds = safe_int(
266 268 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
267 269 cache_on = cache_seconds > 0
268 270 log.debug(
269 271 'Computing REPO TREE for repo_id %s commit_id `%s` '
270 272 'with caching: %s[TTL: %ss]' % (
271 273 repo_id, commit_id, cache_on, cache_seconds or 0))
272 274
273 275 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
274 276 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
275 277
276 278 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
277 279 condition=cache_on)
278 280 def compute_stats(repo_id, commit_id, show_stats):
279 281 code_stats = {}
280 282 size = 0
281 283 try:
282 284 scm_instance = self.db_repo.scm_instance()
283 285 commit = scm_instance.get_commit(commit_id)
284 286
285 287 for node in commit.get_filenodes_generator():
286 288 size += node.size
287 289 if not show_stats:
288 290 continue
289 291 ext = string.lower(node.extension)
290 292 ext_info = LANGUAGES_EXTENSIONS_MAP.get(ext)
291 293 if ext_info:
292 294 if ext in code_stats:
293 295 code_stats[ext]['count'] += 1
294 296 else:
295 297 code_stats[ext] = {"count": 1, "desc": ext_info}
296 298 except (EmptyRepositoryError, CommitDoesNotExistError):
297 299 pass
298 300 return {'size': h.format_byte_size_binary(size),
299 301 'code_stats': code_stats}
300 302
301 303 stats = compute_stats(self.db_repo.repo_id, commit_id, show_stats)
302 304 return stats
303 305
304 306 @LoginRequired()
305 307 @HasRepoPermissionAnyDecorator(
306 308 'repository.read', 'repository.write', 'repository.admin')
307 309 @view_config(
308 310 route_name='repo_refs_data', request_method='GET',
309 311 renderer='json_ext')
310 312 def repo_refs_data(self):
311 313 _ = self.request.translate
312 314 self.load_default_context()
313 315
314 316 repo = self.rhodecode_vcs_repo
315 317 refs_to_create = [
316 318 (_("Branch"), repo.branches, 'branch'),
317 319 (_("Tag"), repo.tags, 'tag'),
318 320 (_("Bookmark"), repo.bookmarks, 'book'),
319 321 ]
320 322 res = self._create_reference_data(
321 323 repo, self.db_repo_name, refs_to_create)
322 324 data = {
323 325 'more': False,
324 326 'results': res
325 327 }
326 328 return data
327 329
328 330 @LoginRequired()
329 331 @HasRepoPermissionAnyDecorator(
330 332 'repository.read', 'repository.write', 'repository.admin')
331 333 @view_config(
332 334 route_name='repo_refs_changelog_data', request_method='GET',
333 335 renderer='json_ext')
334 336 def repo_refs_changelog_data(self):
335 337 _ = self.request.translate
336 338 self.load_default_context()
337 339
338 340 repo = self.rhodecode_vcs_repo
339 341
340 342 refs_to_create = [
341 343 (_("Branches"), repo.branches, 'branch'),
342 344 (_("Closed branches"), repo.branches_closed, 'branch_closed'),
343 345 # TODO: enable when vcs can handle bookmarks filters
344 346 # (_("Bookmarks"), repo.bookmarks, "book"),
345 347 ]
346 348 res = self._create_reference_data(
347 349 repo, self.db_repo_name, refs_to_create)
348 350 data = {
349 351 'more': False,
350 352 'results': res
351 353 }
352 354 return data
353 355
354 356 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
355 357 format_ref_id = get_format_ref_id(repo)
356 358
357 359 result = []
358 360 for title, refs, ref_type in refs_to_create:
359 361 if refs:
360 362 result.append({
361 363 'text': title,
362 364 'children': self._create_reference_items(
363 365 repo, full_repo_name, refs, ref_type,
364 366 format_ref_id),
365 367 })
366 368 return result
367 369
368 370 def _create_reference_items(self, repo, full_repo_name, refs, ref_type,
369 371 format_ref_id):
370 372 result = []
371 373 is_svn = h.is_svn(repo)
372 374 for ref_name, raw_id in refs.iteritems():
373 375 files_url = self._create_files_url(
374 376 repo, full_repo_name, ref_name, raw_id, is_svn)
375 377 result.append({
376 378 'text': ref_name,
377 379 'id': format_ref_id(ref_name, raw_id),
378 380 'raw_id': raw_id,
379 381 'type': ref_type,
380 382 'files_url': files_url,
381 383 })
382 384 return result
383 385
384 386 def _create_files_url(self, repo, full_repo_name, ref_name, raw_id, is_svn):
385 387 use_commit_id = '/' in ref_name or is_svn
386 388 return h.route_path(
387 389 'repo_files',
388 390 repo_name=full_repo_name,
389 391 f_path=ref_name if is_svn else '',
390 392 commit_id=raw_id if use_commit_id else ref_name,
391 393 _query=dict(at=ref_name))
General Comments 0
You need to be logged in to leave comments. Login now