##// END OF EJS Templates
caches: updated cache backend to new vcsserver caches implementation.
marcink -
r3848:fdb508f1 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,57 +1,57 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 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 import os
21 import os
22 import sys
22 import sys
23 import platform
23 import platform
24
24
25 VERSION = tuple(open(os.path.join(
25 VERSION = tuple(open(os.path.join(
26 os.path.dirname(__file__), 'VERSION')).read().split('.'))
26 os.path.dirname(__file__), 'VERSION')).read().split('.'))
27
27
28 BACKENDS = {
28 BACKENDS = {
29 'hg': 'Mercurial repository',
29 'hg': 'Mercurial repository',
30 'git': 'Git repository',
30 'git': 'Git repository',
31 'svn': 'Subversion repository',
31 'svn': 'Subversion repository',
32 }
32 }
33
33
34 CELERY_ENABLED = False
34 CELERY_ENABLED = False
35 CELERY_EAGER = False
35 CELERY_EAGER = False
36
36
37 # link to config for pyramid
37 # link to config for pyramid
38 CONFIG = {}
38 CONFIG = {}
39
39
40 # Populated with the settings dictionary from application init in
40 # Populated with the settings dictionary from application init in
41 # rhodecode.conf.environment.load_pyramid_environment
41 # rhodecode.conf.environment.load_pyramid_environment
42 PYRAMID_SETTINGS = {}
42 PYRAMID_SETTINGS = {}
43
43
44 # Linked module for extensions
44 # Linked module for extensions
45 EXTENSIONS = {}
45 EXTENSIONS = {}
46
46
47 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
47 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
48 __dbversion__ = 98 # defines current db version for migrations
48 __dbversion__ = 99 # defines current db version for migrations
49 __platform__ = platform.system()
49 __platform__ = platform.system()
50 __license__ = 'AGPLv3, and Commercial License'
50 __license__ = 'AGPLv3, and Commercial License'
51 __author__ = 'RhodeCode GmbH'
51 __author__ = 'RhodeCode GmbH'
52 __url__ = 'https://code.rhodecode.com'
52 __url__ = 'https://code.rhodecode.com'
53
53
54 is_windows = __platform__ in ['Windows']
54 is_windows = __platform__ in ['Windows']
55 is_unix = not is_windows
55 is_unix = not is_windows
56 is_test = False
56 is_test = False
57 disable_error_handler = False
57 disable_error_handler = False
@@ -1,501 +1,500 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 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 import logging
22 import logging
23 import collections
23 import collections
24
24
25 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
25 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
26 from pyramid.view import view_config
26 from pyramid.view import view_config
27 from pyramid.renderers import render
27 from pyramid.renderers import render
28 from pyramid.response import Response
28 from pyramid.response import Response
29
29
30 from rhodecode.apps._base import RepoAppView
30 from rhodecode.apps._base import RepoAppView
31
31
32 from rhodecode.lib import diffs, codeblocks
32 from rhodecode.lib import diffs, codeblocks
33 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
34 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired)
34 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired)
35
35
36 from rhodecode.lib.compat import OrderedDict
36 from rhodecode.lib.compat import OrderedDict
37 from rhodecode.lib.diffs import (
37 from rhodecode.lib.diffs import (
38 cache_diff, load_cached_diff, diff_cache_exist, get_diff_context,
38 cache_diff, load_cached_diff, diff_cache_exist, get_diff_context,
39 get_diff_whitespace_flag)
39 get_diff_whitespace_flag)
40 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
40 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
41 import rhodecode.lib.helpers as h
41 import rhodecode.lib.helpers as h
42 from rhodecode.lib.utils2 import safe_unicode, str2bool
42 from rhodecode.lib.utils2 import safe_unicode, str2bool
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 RepositoryError, CommitDoesNotExistError)
45 RepositoryError, CommitDoesNotExistError)
46 from rhodecode.model.db import ChangesetComment, ChangesetStatus
46 from rhodecode.model.db import ChangesetComment, ChangesetStatus
47 from rhodecode.model.changeset_status import ChangesetStatusModel
47 from rhodecode.model.changeset_status import ChangesetStatusModel
48 from rhodecode.model.comment import CommentsModel
48 from rhodecode.model.comment import CommentsModel
49 from rhodecode.model.meta import Session
49 from rhodecode.model.meta import Session
50 from rhodecode.model.settings import VcsSettingsModel
50 from rhodecode.model.settings import VcsSettingsModel
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 def _update_with_GET(params, request):
55 def _update_with_GET(params, request):
56 for k in ['diff1', 'diff2', 'diff']:
56 for k in ['diff1', 'diff2', 'diff']:
57 params[k] += request.GET.getall(k)
57 params[k] += request.GET.getall(k)
58
58
59
59
60
61
62
63 class RepoCommitsView(RepoAppView):
60 class RepoCommitsView(RepoAppView):
64 def load_default_context(self):
61 def load_default_context(self):
65 c = self._get_local_tmpl_context(include_app_defaults=True)
62 c = self._get_local_tmpl_context(include_app_defaults=True)
66 c.rhodecode_repo = self.rhodecode_vcs_repo
63 c.rhodecode_repo = self.rhodecode_vcs_repo
67
64
68 return c
65 return c
69
66
70 def _is_diff_cache_enabled(self, target_repo):
67 def _is_diff_cache_enabled(self, target_repo):
71 caching_enabled = self._get_general_setting(
68 caching_enabled = self._get_general_setting(
72 target_repo, 'rhodecode_diff_cache')
69 target_repo, 'rhodecode_diff_cache')
73 log.debug('Diff caching enabled: %s', caching_enabled)
70 log.debug('Diff caching enabled: %s', caching_enabled)
74 return caching_enabled
71 return caching_enabled
75
72
76 def _commit(self, commit_id_range, method):
73 def _commit(self, commit_id_range, method):
77 _ = self.request.translate
74 _ = self.request.translate
78 c = self.load_default_context()
75 c = self.load_default_context()
79 c.fulldiff = self.request.GET.get('fulldiff')
76 c.fulldiff = self.request.GET.get('fulldiff')
80
77
81 # fetch global flags of ignore ws or context lines
78 # fetch global flags of ignore ws or context lines
82 diff_context = get_diff_context(self.request)
79 diff_context = get_diff_context(self.request)
83 hide_whitespace_changes = get_diff_whitespace_flag(self.request)
80 hide_whitespace_changes = get_diff_whitespace_flag(self.request)
84
81
85 # diff_limit will cut off the whole diff if the limit is applied
82 # diff_limit will cut off the whole diff if the limit is applied
86 # otherwise it will just hide the big files from the front-end
83 # otherwise it will just hide the big files from the front-end
87 diff_limit = c.visual.cut_off_limit_diff
84 diff_limit = c.visual.cut_off_limit_diff
88 file_limit = c.visual.cut_off_limit_file
85 file_limit = c.visual.cut_off_limit_file
89
86
90 # get ranges of commit ids if preset
87 # get ranges of commit ids if preset
91 commit_range = commit_id_range.split('...')[:2]
88 commit_range = commit_id_range.split('...')[:2]
92
89
93 try:
90 try:
94 pre_load = ['affected_files', 'author', 'branch', 'date',
91 pre_load = ['affected_files', 'author', 'branch', 'date',
95 'message', 'parents']
92 'message', 'parents']
93 if self.rhodecode_vcs_repo.alias == 'hg':
94 pre_load += ['hidden', 'obsolete', 'phase']
96
95
97 if len(commit_range) == 2:
96 if len(commit_range) == 2:
98 commits = self.rhodecode_vcs_repo.get_commits(
97 commits = self.rhodecode_vcs_repo.get_commits(
99 start_id=commit_range[0], end_id=commit_range[1],
98 start_id=commit_range[0], end_id=commit_range[1],
100 pre_load=pre_load, translate_tags=False)
99 pre_load=pre_load, translate_tags=False)
101 commits = list(commits)
100 commits = list(commits)
102 else:
101 else:
103 commits = [self.rhodecode_vcs_repo.get_commit(
102 commits = [self.rhodecode_vcs_repo.get_commit(
104 commit_id=commit_id_range, pre_load=pre_load)]
103 commit_id=commit_id_range, pre_load=pre_load)]
105
104
106 c.commit_ranges = commits
105 c.commit_ranges = commits
107 if not c.commit_ranges:
106 if not c.commit_ranges:
108 raise RepositoryError('The commit range returned an empty result')
107 raise RepositoryError('The commit range returned an empty result')
109 except CommitDoesNotExistError as e:
108 except CommitDoesNotExistError as e:
110 msg = _('No such commit exists. Org exception: `{}`').format(e)
109 msg = _('No such commit exists. Org exception: `{}`').format(e)
111 h.flash(msg, category='error')
110 h.flash(msg, category='error')
112 raise HTTPNotFound()
111 raise HTTPNotFound()
113 except Exception:
112 except Exception:
114 log.exception("General failure")
113 log.exception("General failure")
115 raise HTTPNotFound()
114 raise HTTPNotFound()
116
115
117 c.changes = OrderedDict()
116 c.changes = OrderedDict()
118 c.lines_added = 0
117 c.lines_added = 0
119 c.lines_deleted = 0
118 c.lines_deleted = 0
120
119
121 # auto collapse if we have more than limit
120 # auto collapse if we have more than limit
122 collapse_limit = diffs.DiffProcessor._collapse_commits_over
121 collapse_limit = diffs.DiffProcessor._collapse_commits_over
123 c.collapse_all_commits = len(c.commit_ranges) > collapse_limit
122 c.collapse_all_commits = len(c.commit_ranges) > collapse_limit
124
123
125 c.commit_statuses = ChangesetStatus.STATUSES
124 c.commit_statuses = ChangesetStatus.STATUSES
126 c.inline_comments = []
125 c.inline_comments = []
127 c.files = []
126 c.files = []
128
127
129 c.statuses = []
128 c.statuses = []
130 c.comments = []
129 c.comments = []
131 c.unresolved_comments = []
130 c.unresolved_comments = []
132 if len(c.commit_ranges) == 1:
131 if len(c.commit_ranges) == 1:
133 commit = c.commit_ranges[0]
132 commit = c.commit_ranges[0]
134 c.comments = CommentsModel().get_comments(
133 c.comments = CommentsModel().get_comments(
135 self.db_repo.repo_id,
134 self.db_repo.repo_id,
136 revision=commit.raw_id)
135 revision=commit.raw_id)
137 c.statuses.append(ChangesetStatusModel().get_status(
136 c.statuses.append(ChangesetStatusModel().get_status(
138 self.db_repo.repo_id, commit.raw_id))
137 self.db_repo.repo_id, commit.raw_id))
139 # comments from PR
138 # comments from PR
140 statuses = ChangesetStatusModel().get_statuses(
139 statuses = ChangesetStatusModel().get_statuses(
141 self.db_repo.repo_id, commit.raw_id,
140 self.db_repo.repo_id, commit.raw_id,
142 with_revisions=True)
141 with_revisions=True)
143 prs = set(st.pull_request for st in statuses
142 prs = set(st.pull_request for st in statuses
144 if st.pull_request is not None)
143 if st.pull_request is not None)
145 # from associated statuses, check the pull requests, and
144 # from associated statuses, check the pull requests, and
146 # show comments from them
145 # show comments from them
147 for pr in prs:
146 for pr in prs:
148 c.comments.extend(pr.comments)
147 c.comments.extend(pr.comments)
149
148
150 c.unresolved_comments = CommentsModel()\
149 c.unresolved_comments = CommentsModel()\
151 .get_commit_unresolved_todos(commit.raw_id)
150 .get_commit_unresolved_todos(commit.raw_id)
152
151
153 diff = None
152 diff = None
154 # Iterate over ranges (default commit view is always one commit)
153 # Iterate over ranges (default commit view is always one commit)
155 for commit in c.commit_ranges:
154 for commit in c.commit_ranges:
156 c.changes[commit.raw_id] = []
155 c.changes[commit.raw_id] = []
157
156
158 commit2 = commit
157 commit2 = commit
159 commit1 = commit.first_parent
158 commit1 = commit.first_parent
160
159
161 if method == 'show':
160 if method == 'show':
162 inline_comments = CommentsModel().get_inline_comments(
161 inline_comments = CommentsModel().get_inline_comments(
163 self.db_repo.repo_id, revision=commit.raw_id)
162 self.db_repo.repo_id, revision=commit.raw_id)
164 c.inline_cnt = CommentsModel().get_inline_comments_count(
163 c.inline_cnt = CommentsModel().get_inline_comments_count(
165 inline_comments)
164 inline_comments)
166 c.inline_comments = inline_comments
165 c.inline_comments = inline_comments
167
166
168 cache_path = self.rhodecode_vcs_repo.get_create_shadow_cache_pr_path(
167 cache_path = self.rhodecode_vcs_repo.get_create_shadow_cache_pr_path(
169 self.db_repo)
168 self.db_repo)
170 cache_file_path = diff_cache_exist(
169 cache_file_path = diff_cache_exist(
171 cache_path, 'diff', commit.raw_id,
170 cache_path, 'diff', commit.raw_id,
172 hide_whitespace_changes, diff_context, c.fulldiff)
171 hide_whitespace_changes, diff_context, c.fulldiff)
173
172
174 caching_enabled = self._is_diff_cache_enabled(self.db_repo)
173 caching_enabled = self._is_diff_cache_enabled(self.db_repo)
175 force_recache = str2bool(self.request.GET.get('force_recache'))
174 force_recache = str2bool(self.request.GET.get('force_recache'))
176
175
177 cached_diff = None
176 cached_diff = None
178 if caching_enabled:
177 if caching_enabled:
179 cached_diff = load_cached_diff(cache_file_path)
178 cached_diff = load_cached_diff(cache_file_path)
180
179
181 has_proper_diff_cache = cached_diff and cached_diff.get('diff')
180 has_proper_diff_cache = cached_diff and cached_diff.get('diff')
182 if not force_recache and has_proper_diff_cache:
181 if not force_recache and has_proper_diff_cache:
183 diffset = cached_diff['diff']
182 diffset = cached_diff['diff']
184 else:
183 else:
185 vcs_diff = self.rhodecode_vcs_repo.get_diff(
184 vcs_diff = self.rhodecode_vcs_repo.get_diff(
186 commit1, commit2,
185 commit1, commit2,
187 ignore_whitespace=hide_whitespace_changes,
186 ignore_whitespace=hide_whitespace_changes,
188 context=diff_context)
187 context=diff_context)
189
188
190 diff_processor = diffs.DiffProcessor(
189 diff_processor = diffs.DiffProcessor(
191 vcs_diff, format='newdiff', diff_limit=diff_limit,
190 vcs_diff, format='newdiff', diff_limit=diff_limit,
192 file_limit=file_limit, show_full_diff=c.fulldiff)
191 file_limit=file_limit, show_full_diff=c.fulldiff)
193
192
194 _parsed = diff_processor.prepare()
193 _parsed = diff_processor.prepare()
195
194
196 diffset = codeblocks.DiffSet(
195 diffset = codeblocks.DiffSet(
197 repo_name=self.db_repo_name,
196 repo_name=self.db_repo_name,
198 source_node_getter=codeblocks.diffset_node_getter(commit1),
197 source_node_getter=codeblocks.diffset_node_getter(commit1),
199 target_node_getter=codeblocks.diffset_node_getter(commit2))
198 target_node_getter=codeblocks.diffset_node_getter(commit2))
200
199
201 diffset = self.path_filter.render_patchset_filtered(
200 diffset = self.path_filter.render_patchset_filtered(
202 diffset, _parsed, commit1.raw_id, commit2.raw_id)
201 diffset, _parsed, commit1.raw_id, commit2.raw_id)
203
202
204 # save cached diff
203 # save cached diff
205 if caching_enabled:
204 if caching_enabled:
206 cache_diff(cache_file_path, diffset, None)
205 cache_diff(cache_file_path, diffset, None)
207
206
208 c.limited_diff = diffset.limited_diff
207 c.limited_diff = diffset.limited_diff
209 c.changes[commit.raw_id] = diffset
208 c.changes[commit.raw_id] = diffset
210 else:
209 else:
211 # TODO(marcink): no cache usage here...
210 # TODO(marcink): no cache usage here...
212 _diff = self.rhodecode_vcs_repo.get_diff(
211 _diff = self.rhodecode_vcs_repo.get_diff(
213 commit1, commit2,
212 commit1, commit2,
214 ignore_whitespace=hide_whitespace_changes, context=diff_context)
213 ignore_whitespace=hide_whitespace_changes, context=diff_context)
215 diff_processor = diffs.DiffProcessor(
214 diff_processor = diffs.DiffProcessor(
216 _diff, format='newdiff', diff_limit=diff_limit,
215 _diff, format='newdiff', diff_limit=diff_limit,
217 file_limit=file_limit, show_full_diff=c.fulldiff)
216 file_limit=file_limit, show_full_diff=c.fulldiff)
218 # downloads/raw we only need RAW diff nothing else
217 # downloads/raw we only need RAW diff nothing else
219 diff = self.path_filter.get_raw_patch(diff_processor)
218 diff = self.path_filter.get_raw_patch(diff_processor)
220 c.changes[commit.raw_id] = [None, None, None, None, diff, None, None]
219 c.changes[commit.raw_id] = [None, None, None, None, diff, None, None]
221
220
222 # sort comments by how they were generated
221 # sort comments by how they were generated
223 c.comments = sorted(c.comments, key=lambda x: x.comment_id)
222 c.comments = sorted(c.comments, key=lambda x: x.comment_id)
224
223
225 if len(c.commit_ranges) == 1:
224 if len(c.commit_ranges) == 1:
226 c.commit = c.commit_ranges[0]
225 c.commit = c.commit_ranges[0]
227 c.parent_tmpl = ''.join(
226 c.parent_tmpl = ''.join(
228 '# Parent %s\n' % x.raw_id for x in c.commit.parents)
227 '# Parent %s\n' % x.raw_id for x in c.commit.parents)
229
228
230 if method == 'download':
229 if method == 'download':
231 response = Response(diff)
230 response = Response(diff)
232 response.content_type = 'text/plain'
231 response.content_type = 'text/plain'
233 response.content_disposition = (
232 response.content_disposition = (
234 'attachment; filename=%s.diff' % commit_id_range[:12])
233 'attachment; filename=%s.diff' % commit_id_range[:12])
235 return response
234 return response
236 elif method == 'patch':
235 elif method == 'patch':
237 c.diff = safe_unicode(diff)
236 c.diff = safe_unicode(diff)
238 patch = render(
237 patch = render(
239 'rhodecode:templates/changeset/patch_changeset.mako',
238 'rhodecode:templates/changeset/patch_changeset.mako',
240 self._get_template_context(c), self.request)
239 self._get_template_context(c), self.request)
241 response = Response(patch)
240 response = Response(patch)
242 response.content_type = 'text/plain'
241 response.content_type = 'text/plain'
243 return response
242 return response
244 elif method == 'raw':
243 elif method == 'raw':
245 response = Response(diff)
244 response = Response(diff)
246 response.content_type = 'text/plain'
245 response.content_type = 'text/plain'
247 return response
246 return response
248 elif method == 'show':
247 elif method == 'show':
249 if len(c.commit_ranges) == 1:
248 if len(c.commit_ranges) == 1:
250 html = render(
249 html = render(
251 'rhodecode:templates/changeset/changeset.mako',
250 'rhodecode:templates/changeset/changeset.mako',
252 self._get_template_context(c), self.request)
251 self._get_template_context(c), self.request)
253 return Response(html)
252 return Response(html)
254 else:
253 else:
255 c.ancestor = None
254 c.ancestor = None
256 c.target_repo = self.db_repo
255 c.target_repo = self.db_repo
257 html = render(
256 html = render(
258 'rhodecode:templates/changeset/changeset_range.mako',
257 'rhodecode:templates/changeset/changeset_range.mako',
259 self._get_template_context(c), self.request)
258 self._get_template_context(c), self.request)
260 return Response(html)
259 return Response(html)
261
260
262 raise HTTPBadRequest()
261 raise HTTPBadRequest()
263
262
264 @LoginRequired()
263 @LoginRequired()
265 @HasRepoPermissionAnyDecorator(
264 @HasRepoPermissionAnyDecorator(
266 'repository.read', 'repository.write', 'repository.admin')
265 'repository.read', 'repository.write', 'repository.admin')
267 @view_config(
266 @view_config(
268 route_name='repo_commit', request_method='GET',
267 route_name='repo_commit', request_method='GET',
269 renderer=None)
268 renderer=None)
270 def repo_commit_show(self):
269 def repo_commit_show(self):
271 commit_id = self.request.matchdict['commit_id']
270 commit_id = self.request.matchdict['commit_id']
272 return self._commit(commit_id, method='show')
271 return self._commit(commit_id, method='show')
273
272
274 @LoginRequired()
273 @LoginRequired()
275 @HasRepoPermissionAnyDecorator(
274 @HasRepoPermissionAnyDecorator(
276 'repository.read', 'repository.write', 'repository.admin')
275 'repository.read', 'repository.write', 'repository.admin')
277 @view_config(
276 @view_config(
278 route_name='repo_commit_raw', request_method='GET',
277 route_name='repo_commit_raw', request_method='GET',
279 renderer=None)
278 renderer=None)
280 @view_config(
279 @view_config(
281 route_name='repo_commit_raw_deprecated', request_method='GET',
280 route_name='repo_commit_raw_deprecated', request_method='GET',
282 renderer=None)
281 renderer=None)
283 def repo_commit_raw(self):
282 def repo_commit_raw(self):
284 commit_id = self.request.matchdict['commit_id']
283 commit_id = self.request.matchdict['commit_id']
285 return self._commit(commit_id, method='raw')
284 return self._commit(commit_id, method='raw')
286
285
287 @LoginRequired()
286 @LoginRequired()
288 @HasRepoPermissionAnyDecorator(
287 @HasRepoPermissionAnyDecorator(
289 'repository.read', 'repository.write', 'repository.admin')
288 'repository.read', 'repository.write', 'repository.admin')
290 @view_config(
289 @view_config(
291 route_name='repo_commit_patch', request_method='GET',
290 route_name='repo_commit_patch', request_method='GET',
292 renderer=None)
291 renderer=None)
293 def repo_commit_patch(self):
292 def repo_commit_patch(self):
294 commit_id = self.request.matchdict['commit_id']
293 commit_id = self.request.matchdict['commit_id']
295 return self._commit(commit_id, method='patch')
294 return self._commit(commit_id, method='patch')
296
295
297 @LoginRequired()
296 @LoginRequired()
298 @HasRepoPermissionAnyDecorator(
297 @HasRepoPermissionAnyDecorator(
299 'repository.read', 'repository.write', 'repository.admin')
298 'repository.read', 'repository.write', 'repository.admin')
300 @view_config(
299 @view_config(
301 route_name='repo_commit_download', request_method='GET',
300 route_name='repo_commit_download', request_method='GET',
302 renderer=None)
301 renderer=None)
303 def repo_commit_download(self):
302 def repo_commit_download(self):
304 commit_id = self.request.matchdict['commit_id']
303 commit_id = self.request.matchdict['commit_id']
305 return self._commit(commit_id, method='download')
304 return self._commit(commit_id, method='download')
306
305
307 @LoginRequired()
306 @LoginRequired()
308 @NotAnonymous()
307 @NotAnonymous()
309 @HasRepoPermissionAnyDecorator(
308 @HasRepoPermissionAnyDecorator(
310 'repository.read', 'repository.write', 'repository.admin')
309 'repository.read', 'repository.write', 'repository.admin')
311 @CSRFRequired()
310 @CSRFRequired()
312 @view_config(
311 @view_config(
313 route_name='repo_commit_comment_create', request_method='POST',
312 route_name='repo_commit_comment_create', request_method='POST',
314 renderer='json_ext')
313 renderer='json_ext')
315 def repo_commit_comment_create(self):
314 def repo_commit_comment_create(self):
316 _ = self.request.translate
315 _ = self.request.translate
317 commit_id = self.request.matchdict['commit_id']
316 commit_id = self.request.matchdict['commit_id']
318
317
319 c = self.load_default_context()
318 c = self.load_default_context()
320 status = self.request.POST.get('changeset_status', None)
319 status = self.request.POST.get('changeset_status', None)
321 text = self.request.POST.get('text')
320 text = self.request.POST.get('text')
322 comment_type = self.request.POST.get('comment_type')
321 comment_type = self.request.POST.get('comment_type')
323 resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
322 resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
324
323
325 if status:
324 if status:
326 text = text or (_('Status change %(transition_icon)s %(status)s')
325 text = text or (_('Status change %(transition_icon)s %(status)s')
327 % {'transition_icon': '>',
326 % {'transition_icon': '>',
328 'status': ChangesetStatus.get_status_lbl(status)})
327 'status': ChangesetStatus.get_status_lbl(status)})
329
328
330 multi_commit_ids = []
329 multi_commit_ids = []
331 for _commit_id in self.request.POST.get('commit_ids', '').split(','):
330 for _commit_id in self.request.POST.get('commit_ids', '').split(','):
332 if _commit_id not in ['', None, EmptyCommit.raw_id]:
331 if _commit_id not in ['', None, EmptyCommit.raw_id]:
333 if _commit_id not in multi_commit_ids:
332 if _commit_id not in multi_commit_ids:
334 multi_commit_ids.append(_commit_id)
333 multi_commit_ids.append(_commit_id)
335
334
336 commit_ids = multi_commit_ids or [commit_id]
335 commit_ids = multi_commit_ids or [commit_id]
337
336
338 comment = None
337 comment = None
339 for current_id in filter(None, commit_ids):
338 for current_id in filter(None, commit_ids):
340 comment = CommentsModel().create(
339 comment = CommentsModel().create(
341 text=text,
340 text=text,
342 repo=self.db_repo.repo_id,
341 repo=self.db_repo.repo_id,
343 user=self._rhodecode_db_user.user_id,
342 user=self._rhodecode_db_user.user_id,
344 commit_id=current_id,
343 commit_id=current_id,
345 f_path=self.request.POST.get('f_path'),
344 f_path=self.request.POST.get('f_path'),
346 line_no=self.request.POST.get('line'),
345 line_no=self.request.POST.get('line'),
347 status_change=(ChangesetStatus.get_status_lbl(status)
346 status_change=(ChangesetStatus.get_status_lbl(status)
348 if status else None),
347 if status else None),
349 status_change_type=status,
348 status_change_type=status,
350 comment_type=comment_type,
349 comment_type=comment_type,
351 resolves_comment_id=resolves_comment_id,
350 resolves_comment_id=resolves_comment_id,
352 auth_user=self._rhodecode_user
351 auth_user=self._rhodecode_user
353 )
352 )
354
353
355 # get status if set !
354 # get status if set !
356 if status:
355 if status:
357 # if latest status was from pull request and it's closed
356 # if latest status was from pull request and it's closed
358 # disallow changing status !
357 # disallow changing status !
359 # dont_allow_on_closed_pull_request = True !
358 # dont_allow_on_closed_pull_request = True !
360
359
361 try:
360 try:
362 ChangesetStatusModel().set_status(
361 ChangesetStatusModel().set_status(
363 self.db_repo.repo_id,
362 self.db_repo.repo_id,
364 status,
363 status,
365 self._rhodecode_db_user.user_id,
364 self._rhodecode_db_user.user_id,
366 comment,
365 comment,
367 revision=current_id,
366 revision=current_id,
368 dont_allow_on_closed_pull_request=True
367 dont_allow_on_closed_pull_request=True
369 )
368 )
370 except StatusChangeOnClosedPullRequestError:
369 except StatusChangeOnClosedPullRequestError:
371 msg = _('Changing the status of a commit associated with '
370 msg = _('Changing the status of a commit associated with '
372 'a closed pull request is not allowed')
371 'a closed pull request is not allowed')
373 log.exception(msg)
372 log.exception(msg)
374 h.flash(msg, category='warning')
373 h.flash(msg, category='warning')
375 raise HTTPFound(h.route_path(
374 raise HTTPFound(h.route_path(
376 'repo_commit', repo_name=self.db_repo_name,
375 'repo_commit', repo_name=self.db_repo_name,
377 commit_id=current_id))
376 commit_id=current_id))
378
377
379 # finalize, commit and redirect
378 # finalize, commit and redirect
380 Session().commit()
379 Session().commit()
381
380
382 data = {
381 data = {
383 'target_id': h.safeid(h.safe_unicode(
382 'target_id': h.safeid(h.safe_unicode(
384 self.request.POST.get('f_path'))),
383 self.request.POST.get('f_path'))),
385 }
384 }
386 if comment:
385 if comment:
387 c.co = comment
386 c.co = comment
388 rendered_comment = render(
387 rendered_comment = render(
389 'rhodecode:templates/changeset/changeset_comment_block.mako',
388 'rhodecode:templates/changeset/changeset_comment_block.mako',
390 self._get_template_context(c), self.request)
389 self._get_template_context(c), self.request)
391
390
392 data.update(comment.get_dict())
391 data.update(comment.get_dict())
393 data.update({'rendered_text': rendered_comment})
392 data.update({'rendered_text': rendered_comment})
394
393
395 return data
394 return data
396
395
397 @LoginRequired()
396 @LoginRequired()
398 @NotAnonymous()
397 @NotAnonymous()
399 @HasRepoPermissionAnyDecorator(
398 @HasRepoPermissionAnyDecorator(
400 'repository.read', 'repository.write', 'repository.admin')
399 'repository.read', 'repository.write', 'repository.admin')
401 @CSRFRequired()
400 @CSRFRequired()
402 @view_config(
401 @view_config(
403 route_name='repo_commit_comment_preview', request_method='POST',
402 route_name='repo_commit_comment_preview', request_method='POST',
404 renderer='string', xhr=True)
403 renderer='string', xhr=True)
405 def repo_commit_comment_preview(self):
404 def repo_commit_comment_preview(self):
406 # Technically a CSRF token is not needed as no state changes with this
405 # Technically a CSRF token is not needed as no state changes with this
407 # call. However, as this is a POST is better to have it, so automated
406 # call. However, as this is a POST is better to have it, so automated
408 # tools don't flag it as potential CSRF.
407 # tools don't flag it as potential CSRF.
409 # Post is required because the payload could be bigger than the maximum
408 # Post is required because the payload could be bigger than the maximum
410 # allowed by GET.
409 # allowed by GET.
411
410
412 text = self.request.POST.get('text')
411 text = self.request.POST.get('text')
413 renderer = self.request.POST.get('renderer') or 'rst'
412 renderer = self.request.POST.get('renderer') or 'rst'
414 if text:
413 if text:
415 return h.render(text, renderer=renderer, mentions=True)
414 return h.render(text, renderer=renderer, mentions=True)
416 return ''
415 return ''
417
416
418 @LoginRequired()
417 @LoginRequired()
419 @NotAnonymous()
418 @NotAnonymous()
420 @HasRepoPermissionAnyDecorator(
419 @HasRepoPermissionAnyDecorator(
421 'repository.read', 'repository.write', 'repository.admin')
420 'repository.read', 'repository.write', 'repository.admin')
422 @CSRFRequired()
421 @CSRFRequired()
423 @view_config(
422 @view_config(
424 route_name='repo_commit_comment_delete', request_method='POST',
423 route_name='repo_commit_comment_delete', request_method='POST',
425 renderer='json_ext')
424 renderer='json_ext')
426 def repo_commit_comment_delete(self):
425 def repo_commit_comment_delete(self):
427 commit_id = self.request.matchdict['commit_id']
426 commit_id = self.request.matchdict['commit_id']
428 comment_id = self.request.matchdict['comment_id']
427 comment_id = self.request.matchdict['comment_id']
429
428
430 comment = ChangesetComment.get_or_404(comment_id)
429 comment = ChangesetComment.get_or_404(comment_id)
431 if not comment:
430 if not comment:
432 log.debug('Comment with id:%s not found, skipping', comment_id)
431 log.debug('Comment with id:%s not found, skipping', comment_id)
433 # comment already deleted in another call probably
432 # comment already deleted in another call probably
434 return True
433 return True
435
434
436 is_repo_admin = h.HasRepoPermissionAny('repository.admin')(self.db_repo_name)
435 is_repo_admin = h.HasRepoPermissionAny('repository.admin')(self.db_repo_name)
437 super_admin = h.HasPermissionAny('hg.admin')()
436 super_admin = h.HasPermissionAny('hg.admin')()
438 comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
437 comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
439 is_repo_comment = comment.repo.repo_name == self.db_repo_name
438 is_repo_comment = comment.repo.repo_name == self.db_repo_name
440 comment_repo_admin = is_repo_admin and is_repo_comment
439 comment_repo_admin = is_repo_admin and is_repo_comment
441
440
442 if super_admin or comment_owner or comment_repo_admin:
441 if super_admin or comment_owner or comment_repo_admin:
443 CommentsModel().delete(comment=comment, auth_user=self._rhodecode_user)
442 CommentsModel().delete(comment=comment, auth_user=self._rhodecode_user)
444 Session().commit()
443 Session().commit()
445 return True
444 return True
446 else:
445 else:
447 log.warning('No permissions for user %s to delete comment_id: %s',
446 log.warning('No permissions for user %s to delete comment_id: %s',
448 self._rhodecode_db_user, comment_id)
447 self._rhodecode_db_user, comment_id)
449 raise HTTPNotFound()
448 raise HTTPNotFound()
450
449
451 @LoginRequired()
450 @LoginRequired()
452 @HasRepoPermissionAnyDecorator(
451 @HasRepoPermissionAnyDecorator(
453 'repository.read', 'repository.write', 'repository.admin')
452 'repository.read', 'repository.write', 'repository.admin')
454 @view_config(
453 @view_config(
455 route_name='repo_commit_data', request_method='GET',
454 route_name='repo_commit_data', request_method='GET',
456 renderer='json_ext', xhr=True)
455 renderer='json_ext', xhr=True)
457 def repo_commit_data(self):
456 def repo_commit_data(self):
458 commit_id = self.request.matchdict['commit_id']
457 commit_id = self.request.matchdict['commit_id']
459 self.load_default_context()
458 self.load_default_context()
460
459
461 try:
460 try:
462 return self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
461 return self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
463 except CommitDoesNotExistError as e:
462 except CommitDoesNotExistError as e:
464 return EmptyCommit(message=str(e))
463 return EmptyCommit(message=str(e))
465
464
466 @LoginRequired()
465 @LoginRequired()
467 @HasRepoPermissionAnyDecorator(
466 @HasRepoPermissionAnyDecorator(
468 'repository.read', 'repository.write', 'repository.admin')
467 'repository.read', 'repository.write', 'repository.admin')
469 @view_config(
468 @view_config(
470 route_name='repo_commit_children', request_method='GET',
469 route_name='repo_commit_children', request_method='GET',
471 renderer='json_ext', xhr=True)
470 renderer='json_ext', xhr=True)
472 def repo_commit_children(self):
471 def repo_commit_children(self):
473 commit_id = self.request.matchdict['commit_id']
472 commit_id = self.request.matchdict['commit_id']
474 self.load_default_context()
473 self.load_default_context()
475
474
476 try:
475 try:
477 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
476 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
478 children = commit.children
477 children = commit.children
479 except CommitDoesNotExistError:
478 except CommitDoesNotExistError:
480 children = []
479 children = []
481
480
482 result = {"results": children}
481 result = {"results": children}
483 return result
482 return result
484
483
485 @LoginRequired()
484 @LoginRequired()
486 @HasRepoPermissionAnyDecorator(
485 @HasRepoPermissionAnyDecorator(
487 'repository.read', 'repository.write', 'repository.admin')
486 'repository.read', 'repository.write', 'repository.admin')
488 @view_config(
487 @view_config(
489 route_name='repo_commit_parents', request_method='GET',
488 route_name='repo_commit_parents', request_method='GET',
490 renderer='json_ext')
489 renderer='json_ext')
491 def repo_commit_parents(self):
490 def repo_commit_parents(self):
492 commit_id = self.request.matchdict['commit_id']
491 commit_id = self.request.matchdict['commit_id']
493 self.load_default_context()
492 self.load_default_context()
494
493
495 try:
494 try:
496 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
495 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
497 parents = commit.parents
496 parents = commit.parents
498 except CommitDoesNotExistError:
497 except CommitDoesNotExistError:
499 parents = []
498 parents = []
500 result = {"results": parents}
499 result = {"results": parents}
501 return result
500 return result
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now