##// END OF EJS Templates
summary: Improve logging around README handling
johbo -
r767:5902f223 default
parent child Browse files
Show More
@@ -1,300 +1,304 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Summary controller for RhodeCode Enterprise
22 Summary controller for RhodeCode Enterprise
23 """
23 """
24
24
25 import logging
25 import logging
26 from string import lower
26 from string import lower
27
27
28 from pylons import tmpl_context as c, request
28 from pylons import tmpl_context as c, request
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from beaker.cache import cache_region, region_invalidate
30 from beaker.cache import cache_region, region_invalidate
31
31
32 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
32 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
33 from rhodecode.controllers import utils
33 from rhodecode.controllers import utils
34 from rhodecode.controllers.changelog import _load_changelog_summary
34 from rhodecode.controllers.changelog import _load_changelog_summary
35 from rhodecode.lib import caches, helpers as h
35 from rhodecode.lib import caches, helpers as h
36 from rhodecode.lib.utils import jsonify
36 from rhodecode.lib.utils import jsonify
37 from rhodecode.lib.utils2 import safe_str
37 from rhodecode.lib.utils2 import safe_str
38 from rhodecode.lib.auth import (
38 from rhodecode.lib.auth import (
39 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, XHRRequired)
39 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, XHRRequired)
40 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.lib.base import BaseRepoController, render
41 from rhodecode.lib.markup_renderer import MarkupRenderer
41 from rhodecode.lib.markup_renderer import MarkupRenderer
42 from rhodecode.lib.ext_json import json
42 from rhodecode.lib.ext_json import json
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44 from rhodecode.lib.vcs.exceptions import (
44 from rhodecode.lib.vcs.exceptions import (
45 CommitError, EmptyRepositoryError, NodeDoesNotExistError)
45 CommitError, EmptyRepositoryError, NodeDoesNotExistError)
46 from rhodecode.model.db import Statistics, CacheKey, User
46 from rhodecode.model.db import Statistics, CacheKey, User
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class SummaryController(BaseRepoController):
51 class SummaryController(BaseRepoController):
52
52
53 def __before__(self):
53 def __before__(self):
54 super(SummaryController, self).__before__()
54 super(SummaryController, self).__before__()
55
55
56 def __get_readme_data(self, db_repo):
56 def __get_readme_data(self, db_repo):
57 repo_name = db_repo.repo_name
57 repo_name = db_repo.repo_name
58 log.debug('Looking for README file')
58 log.debug('Looking for README file')
59 default_renderer = c.visual.default_renderer
59 default_renderer = c.visual.default_renderer
60
60
61 @cache_region('long_term')
61 @cache_region('long_term')
62 def _generate_readme(cache_key):
62 def _generate_readme(cache_key):
63 readme_data = None
63 readme_data = None
64 readme_file = None
64 readme_file = None
65 try:
65 try:
66 # gets the landing revision or tip if fails
66 # gets the landing revision or tip if fails
67 commit = db_repo.get_landing_commit()
67 commit = db_repo.get_landing_commit()
68 if isinstance(commit, EmptyCommit):
68 if isinstance(commit, EmptyCommit):
69 raise EmptyRepositoryError()
69 raise EmptyRepositoryError()
70 renderer = MarkupRenderer()
70 renderer = MarkupRenderer()
71 for f in renderer.pick_readme_order(default_renderer):
71 for f in renderer.pick_readme_order(default_renderer):
72 try:
72 try:
73 node = commit.get_node(f)
73 node = commit.get_node(f)
74 except NodeDoesNotExistError:
74 except NodeDoesNotExistError:
75 continue
75 continue
76
76
77 if not node.is_file():
77 if not node.is_file():
78 continue
78 continue
79
79
80 readme_file = f
80 readme_file = f
81 log.debug('Found README file `%s` rendering...',
81 log.debug('Found README file `%s` rendering...',
82 readme_file)
82 readme_file)
83 readme_data = renderer.render(node.content,
83 readme_data = renderer.render(node.content,
84 filename=f)
84 filename=f)
85 break
85 break
86 except CommitError:
86 except CommitError:
87 log.exception("Problem getting commit")
87 log.exception(
88 pass
88 "Problem getting commit when trying to render the README.")
89 except EmptyRepositoryError:
89 except EmptyRepositoryError:
90 pass
90 log.debug("Repository is empty, no README to render.")
91 except Exception:
91 except Exception:
92 log.exception("General failure")
92 log.exception("Exception while trying to render the README")
93
93
94 return readme_data, readme_file
94 return readme_data, readme_file
95
95
96 invalidator_context = CacheKey.repo_context_cache(
96 invalidator_context = CacheKey.repo_context_cache(
97 _generate_readme, repo_name, CacheKey.CACHE_TYPE_README)
97 _generate_readme, repo_name, CacheKey.CACHE_TYPE_README)
98
98
99 with invalidator_context as context:
99 with invalidator_context as context:
100 context.invalidate()
100 context.invalidate()
101 computed = context.compute()
101 computed = context.compute()
102
102
103 return computed
103 return computed
104
104
105
106 @LoginRequired()
105 @LoginRequired()
107 @HasRepoPermissionAnyDecorator(
106 @HasRepoPermissionAnyDecorator(
108 'repository.read', 'repository.write', 'repository.admin')
107 'repository.read', 'repository.write', 'repository.admin')
109 def index(self, repo_name):
108 def index(self, repo_name):
109
110 # Prepare the clone URL
111
110 username = ''
112 username = ''
111 if c.rhodecode_user.username != User.DEFAULT_USER:
113 if c.rhodecode_user.username != User.DEFAULT_USER:
112 username = safe_str(c.rhodecode_user.username)
114 username = safe_str(c.rhodecode_user.username)
113
115
114 _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl
116 _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl
115 if '{repo}' in _def_clone_uri:
117 if '{repo}' in _def_clone_uri:
116 _def_clone_uri_by_id = _def_clone_uri.replace(
118 _def_clone_uri_by_id = _def_clone_uri.replace(
117 '{repo}', '_{repoid}')
119 '{repo}', '_{repoid}')
118 elif '{repoid}' in _def_clone_uri:
120 elif '{repoid}' in _def_clone_uri:
119 _def_clone_uri_by_id = _def_clone_uri.replace(
121 _def_clone_uri_by_id = _def_clone_uri.replace(
120 '_{repoid}', '{repo}')
122 '_{repoid}', '{repo}')
121
123
122 c.clone_repo_url = c.rhodecode_db_repo.clone_url(
124 c.clone_repo_url = c.rhodecode_db_repo.clone_url(
123 user=username, uri_tmpl=_def_clone_uri)
125 user=username, uri_tmpl=_def_clone_uri)
124 c.clone_repo_url_id = c.rhodecode_db_repo.clone_url(
126 c.clone_repo_url_id = c.rhodecode_db_repo.clone_url(
125 user=username, uri_tmpl=_def_clone_uri_by_id)
127 user=username, uri_tmpl=_def_clone_uri_by_id)
126
128
129 # If enabled, get statistics data
130
127 c.show_stats = bool(c.rhodecode_db_repo.enable_statistics)
131 c.show_stats = bool(c.rhodecode_db_repo.enable_statistics)
128
132
129 stats = self.sa.query(Statistics)\
133 stats = self.sa.query(Statistics)\
130 .filter(Statistics.repository == c.rhodecode_db_repo)\
134 .filter(Statistics.repository == c.rhodecode_db_repo)\
131 .scalar()
135 .scalar()
132
136
133 c.stats_percentage = 0
137 c.stats_percentage = 0
134
138
135 if stats and stats.languages:
139 if stats and stats.languages:
136 c.no_data = False is c.rhodecode_db_repo.enable_statistics
140 c.no_data = False is c.rhodecode_db_repo.enable_statistics
137 lang_stats_d = json.loads(stats.languages)
141 lang_stats_d = json.loads(stats.languages)
138
142
139 # Sort first by decreasing count and second by the file extension,
143 # Sort first by decreasing count and second by the file extension,
140 # so we have a consistent output.
144 # so we have a consistent output.
141 lang_stats_items = sorted(lang_stats_d.iteritems(),
145 lang_stats_items = sorted(lang_stats_d.iteritems(),
142 key=lambda k: (-k[1], k[0]))[:10]
146 key=lambda k: (-k[1], k[0]))[:10]
143 lang_stats = [(x, {"count": y,
147 lang_stats = [(x, {"count": y,
144 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
148 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
145 for x, y in lang_stats_items]
149 for x, y in lang_stats_items]
146
150
147 c.trending_languages = json.dumps(lang_stats)
151 c.trending_languages = json.dumps(lang_stats)
148 else:
152 else:
149 c.no_data = True
153 c.no_data = True
150 c.trending_languages = json.dumps({})
154 c.trending_languages = json.dumps({})
151
155
152 c.enable_downloads = c.rhodecode_db_repo.enable_downloads
156 c.enable_downloads = c.rhodecode_db_repo.enable_downloads
153 c.repository_followers = self.scm_model.get_followers(
157 c.repository_followers = self.scm_model.get_followers(
154 c.rhodecode_db_repo)
158 c.rhodecode_db_repo)
155 c.repository_forks = self.scm_model.get_forks(c.rhodecode_db_repo)
159 c.repository_forks = self.scm_model.get_forks(c.rhodecode_db_repo)
156 c.repository_is_user_following = self.scm_model.is_following_repo(
160 c.repository_is_user_following = self.scm_model.is_following_repo(
157 c.repo_name, c.rhodecode_user.user_id)
161 c.repo_name, c.rhodecode_user.user_id)
158
162
159 if c.repository_requirements_missing:
163 if c.repository_requirements_missing:
160 return render('summary/missing_requirements.html')
164 return render('summary/missing_requirements.html')
161
165
162 c.readme_data, c.readme_file = \
166 c.readme_data, c.readme_file = \
163 self.__get_readme_data(c.rhodecode_db_repo)
167 self.__get_readme_data(c.rhodecode_db_repo)
164
168
165 _load_changelog_summary()
169 _load_changelog_summary()
166
170
167 if request.is_xhr:
171 if request.is_xhr:
168 return render('changelog/changelog_summary_data.html')
172 return render('changelog/changelog_summary_data.html')
169
173
170 return render('summary/summary.html')
174 return render('summary/summary.html')
171
175
172 @LoginRequired()
176 @LoginRequired()
173 @XHRRequired()
177 @XHRRequired()
174 @HasRepoPermissionAnyDecorator(
178 @HasRepoPermissionAnyDecorator(
175 'repository.read', 'repository.write', 'repository.admin')
179 'repository.read', 'repository.write', 'repository.admin')
176 @jsonify
180 @jsonify
177 def repo_stats(self, repo_name, commit_id):
181 def repo_stats(self, repo_name, commit_id):
178 _namespace = caches.get_repo_namespace_key(
182 _namespace = caches.get_repo_namespace_key(
179 caches.SUMMARY_STATS, repo_name)
183 caches.SUMMARY_STATS, repo_name)
180 show_stats = bool(c.rhodecode_db_repo.enable_statistics)
184 show_stats = bool(c.rhodecode_db_repo.enable_statistics)
181 cache_manager = caches.get_cache_manager('repo_cache_long', _namespace)
185 cache_manager = caches.get_cache_manager('repo_cache_long', _namespace)
182 _cache_key = caches.compute_key_from_params(
186 _cache_key = caches.compute_key_from_params(
183 repo_name, commit_id, show_stats)
187 repo_name, commit_id, show_stats)
184
188
185 def compute_stats():
189 def compute_stats():
186 code_stats = {}
190 code_stats = {}
187 size = 0
191 size = 0
188 try:
192 try:
189 scm_instance = c.rhodecode_db_repo.scm_instance()
193 scm_instance = c.rhodecode_db_repo.scm_instance()
190 commit = scm_instance.get_commit(commit_id)
194 commit = scm_instance.get_commit(commit_id)
191
195
192 for node in commit.get_filenodes_generator():
196 for node in commit.get_filenodes_generator():
193 size += node.size
197 size += node.size
194 if not show_stats:
198 if not show_stats:
195 continue
199 continue
196 ext = lower(node.extension)
200 ext = lower(node.extension)
197 ext_info = LANGUAGES_EXTENSIONS_MAP.get(ext)
201 ext_info = LANGUAGES_EXTENSIONS_MAP.get(ext)
198 if ext_info:
202 if ext_info:
199 if ext in code_stats:
203 if ext in code_stats:
200 code_stats[ext]['count'] += 1
204 code_stats[ext]['count'] += 1
201 else:
205 else:
202 code_stats[ext] = {"count": 1, "desc": ext_info}
206 code_stats[ext] = {"count": 1, "desc": ext_info}
203 except EmptyRepositoryError:
207 except EmptyRepositoryError:
204 pass
208 pass
205 return {'size': h.format_byte_size_binary(size),
209 return {'size': h.format_byte_size_binary(size),
206 'code_stats': code_stats}
210 'code_stats': code_stats}
207
211
208 stats = cache_manager.get(_cache_key, createfunc=compute_stats)
212 stats = cache_manager.get(_cache_key, createfunc=compute_stats)
209 return stats
213 return stats
210
214
211 def _switcher_reference_data(self, repo_name, references, is_svn):
215 def _switcher_reference_data(self, repo_name, references, is_svn):
212 """Prepare reference data for given `references`"""
216 """Prepare reference data for given `references`"""
213 items = []
217 items = []
214 for name, commit_id in references.items():
218 for name, commit_id in references.items():
215 use_commit_id = '/' in name or is_svn
219 use_commit_id = '/' in name or is_svn
216 items.append({
220 items.append({
217 'name': name,
221 'name': name,
218 'commit_id': commit_id,
222 'commit_id': commit_id,
219 'files_url': h.url(
223 'files_url': h.url(
220 'files_home',
224 'files_home',
221 repo_name=repo_name,
225 repo_name=repo_name,
222 f_path=name if is_svn else '',
226 f_path=name if is_svn else '',
223 revision=commit_id if use_commit_id else name,
227 revision=commit_id if use_commit_id else name,
224 at=name)
228 at=name)
225 })
229 })
226 return items
230 return items
227
231
228 @LoginRequired()
232 @LoginRequired()
229 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
233 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
230 'repository.admin')
234 'repository.admin')
231 @jsonify
235 @jsonify
232 def repo_refs_data(self, repo_name):
236 def repo_refs_data(self, repo_name):
233 repo = c.rhodecode_repo
237 repo = c.rhodecode_repo
234 refs_to_create = [
238 refs_to_create = [
235 (_("Branch"), repo.branches, 'branch'),
239 (_("Branch"), repo.branches, 'branch'),
236 (_("Tag"), repo.tags, 'tag'),
240 (_("Tag"), repo.tags, 'tag'),
237 (_("Bookmark"), repo.bookmarks, 'book'),
241 (_("Bookmark"), repo.bookmarks, 'book'),
238 ]
242 ]
239 res = self._create_reference_data(repo, repo_name, refs_to_create)
243 res = self._create_reference_data(repo, repo_name, refs_to_create)
240 data = {
244 data = {
241 'more': False,
245 'more': False,
242 'results': res
246 'results': res
243 }
247 }
244 return data
248 return data
245
249
246 @jsonify
250 @jsonify
247 def repo_refs_changelog_data(self, repo_name):
251 def repo_refs_changelog_data(self, repo_name):
248 repo = c.rhodecode_repo
252 repo = c.rhodecode_repo
249
253
250 refs_to_create = [
254 refs_to_create = [
251 (_("Branches"), repo.branches, 'branch'),
255 (_("Branches"), repo.branches, 'branch'),
252 (_("Closed branches"), repo.branches_closed, 'branch_closed'),
256 (_("Closed branches"), repo.branches_closed, 'branch_closed'),
253 # TODO: enable when vcs can handle bookmarks filters
257 # TODO: enable when vcs can handle bookmarks filters
254 # (_("Bookmarks"), repo.bookmarks, "book"),
258 # (_("Bookmarks"), repo.bookmarks, "book"),
255 ]
259 ]
256 res = self._create_reference_data(repo, repo_name, refs_to_create)
260 res = self._create_reference_data(repo, repo_name, refs_to_create)
257 data = {
261 data = {
258 'more': False,
262 'more': False,
259 'results': res
263 'results': res
260 }
264 }
261 return data
265 return data
262
266
263 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
267 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
264 format_ref_id = utils.get_format_ref_id(repo)
268 format_ref_id = utils.get_format_ref_id(repo)
265
269
266 result = []
270 result = []
267 for title, refs, ref_type in refs_to_create:
271 for title, refs, ref_type in refs_to_create:
268 if refs:
272 if refs:
269 result.append({
273 result.append({
270 'text': title,
274 'text': title,
271 'children': self._create_reference_items(
275 'children': self._create_reference_items(
272 repo, full_repo_name, refs, ref_type, format_ref_id),
276 repo, full_repo_name, refs, ref_type, format_ref_id),
273 })
277 })
274 return result
278 return result
275
279
276 def _create_reference_items(self, repo, full_repo_name, refs, ref_type,
280 def _create_reference_items(self, repo, full_repo_name, refs, ref_type,
277 format_ref_id):
281 format_ref_id):
278 result = []
282 result = []
279 is_svn = h.is_svn(repo)
283 is_svn = h.is_svn(repo)
280 for ref_name, raw_id in refs.iteritems():
284 for ref_name, raw_id in refs.iteritems():
281 files_url = self._create_files_url(
285 files_url = self._create_files_url(
282 repo, full_repo_name, ref_name, raw_id, is_svn)
286 repo, full_repo_name, ref_name, raw_id, is_svn)
283 result.append({
287 result.append({
284 'text': ref_name,
288 'text': ref_name,
285 'id': format_ref_id(ref_name, raw_id),
289 'id': format_ref_id(ref_name, raw_id),
286 'raw_id': raw_id,
290 'raw_id': raw_id,
287 'type': ref_type,
291 'type': ref_type,
288 'files_url': files_url,
292 'files_url': files_url,
289 })
293 })
290 return result
294 return result
291
295
292 def _create_files_url(self, repo, full_repo_name, ref_name, raw_id,
296 def _create_files_url(self, repo, full_repo_name, ref_name, raw_id,
293 is_svn):
297 is_svn):
294 use_commit_id = '/' in ref_name or is_svn
298 use_commit_id = '/' in ref_name or is_svn
295 return h.url(
299 return h.url(
296 'files_home',
300 'files_home',
297 repo_name=full_repo_name,
301 repo_name=full_repo_name,
298 f_path=ref_name if is_svn else '',
302 f_path=ref_name if is_svn else '',
299 revision=raw_id if use_commit_id else ref_name,
303 revision=raw_id if use_commit_id else ref_name,
300 at=ref_name)
304 at=ref_name)
General Comments 0
You need to be logged in to leave comments. Login now