##// END OF EJS Templates
fixes for tests on Windows
marcink -
r2255:95800dad beta
parent child Browse files
Show More
@@ -1,486 +1,487 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.files
3 rhodecode.controllers.files
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Files controller for RhodeCode
6 Files controller for RhodeCode
7
7
8 :created_on: Apr 21, 2010
8 :created_on: Apr 21, 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 os
26 import os
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from pylons import request, response, tmpl_context as c, url
30 from pylons import request, response, tmpl_context as c, url
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32 from pylons.controllers.util import redirect
32 from pylons.controllers.util import redirect
33 from pylons.decorators import jsonify
33 from pylons.decorators import jsonify
34
34
35 from rhodecode.lib import diffs
35 from rhodecode.lib import diffs
36 from rhodecode.lib import helpers as h
36 from rhodecode.lib import helpers as h
37
37
38 from rhodecode.lib.compat import OrderedDict
38 from rhodecode.lib.compat import OrderedDict
39 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
39 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 from rhodecode.lib.base import BaseRepoController, render
41 from rhodecode.lib.base import BaseRepoController, render
42 from rhodecode.lib.utils import EmptyChangeset
42 from rhodecode.lib.utils import EmptyChangeset
43 from rhodecode.lib.vcs.conf import settings
43 from rhodecode.lib.vcs.conf import settings
44 from rhodecode.lib.vcs.exceptions import RepositoryError, \
44 from rhodecode.lib.vcs.exceptions import RepositoryError, \
45 ChangesetDoesNotExistError, EmptyRepositoryError, \
45 ChangesetDoesNotExistError, EmptyRepositoryError, \
46 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
46 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
47 from rhodecode.lib.vcs.nodes import FileNode
47 from rhodecode.lib.vcs.nodes import FileNode
48
48
49 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.scm import ScmModel
50 from rhodecode.model.scm import ScmModel
51 from rhodecode.model.db import Repository
51
52
52 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
53 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
53 _context_url, get_line_ctx, get_ignore_ws
54 _context_url, get_line_ctx, get_ignore_ws
54
55
55
56
56 log = logging.getLogger(__name__)
57 log = logging.getLogger(__name__)
57
58
58
59
59 class FilesController(BaseRepoController):
60 class FilesController(BaseRepoController):
60
61
61 @LoginRequired()
62 @LoginRequired()
62 def __before__(self):
63 def __before__(self):
63 super(FilesController, self).__before__()
64 super(FilesController, self).__before__()
64 c.cut_off_limit = self.cut_off_limit
65 c.cut_off_limit = self.cut_off_limit
65
66
66 def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
67 def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
67 """
68 """
68 Safe way to get changeset if error occur it redirects to tip with
69 Safe way to get changeset if error occur it redirects to tip with
69 proper message
70 proper message
70
71
71 :param rev: revision to fetch
72 :param rev: revision to fetch
72 :param repo_name: repo name to redirect after
73 :param repo_name: repo name to redirect after
73 """
74 """
74
75
75 try:
76 try:
76 return c.rhodecode_repo.get_changeset(rev)
77 return c.rhodecode_repo.get_changeset(rev)
77 except EmptyRepositoryError, e:
78 except EmptyRepositoryError, e:
78 if not redirect_after:
79 if not redirect_after:
79 return None
80 return None
80 url_ = url('files_add_home',
81 url_ = url('files_add_home',
81 repo_name=c.repo_name,
82 repo_name=c.repo_name,
82 revision=0, f_path='')
83 revision=0, f_path='')
83 add_new = '<a href="%s">[%s]</a>' % (url_, _('add new'))
84 add_new = '<a href="%s">[%s]</a>' % (url_, _('add new'))
84 h.flash(h.literal(_('There are no files yet %s' % add_new)),
85 h.flash(h.literal(_('There are no files yet %s' % add_new)),
85 category='warning')
86 category='warning')
86 redirect(h.url('summary_home', repo_name=repo_name))
87 redirect(h.url('summary_home', repo_name=repo_name))
87
88
88 except RepositoryError, e:
89 except RepositoryError, e:
89 h.flash(str(e), category='warning')
90 h.flash(str(e), category='warning')
90 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
91 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
91
92
92 def __get_filenode_or_redirect(self, repo_name, cs, path):
93 def __get_filenode_or_redirect(self, repo_name, cs, path):
93 """
94 """
94 Returns file_node, if error occurs or given path is directory,
95 Returns file_node, if error occurs or given path is directory,
95 it'll redirect to top level path
96 it'll redirect to top level path
96
97
97 :param repo_name: repo_name
98 :param repo_name: repo_name
98 :param cs: given changeset
99 :param cs: given changeset
99 :param path: path to lookup
100 :param path: path to lookup
100 """
101 """
101
102
102 try:
103 try:
103 file_node = cs.get_node(path)
104 file_node = cs.get_node(path)
104 if file_node.is_dir():
105 if file_node.is_dir():
105 raise RepositoryError('given path is a directory')
106 raise RepositoryError('given path is a directory')
106 except RepositoryError, e:
107 except RepositoryError, e:
107 h.flash(str(e), category='warning')
108 h.flash(str(e), category='warning')
108 redirect(h.url('files_home', repo_name=repo_name,
109 redirect(h.url('files_home', repo_name=repo_name,
109 revision=cs.raw_id))
110 revision=cs.raw_id))
110
111
111 return file_node
112 return file_node
112
113
113 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
114 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
114 'repository.admin')
115 'repository.admin')
115 def index(self, repo_name, revision, f_path, annotate=False):
116 def index(self, repo_name, revision, f_path, annotate=False):
116 # redirect to given revision from form if given
117 # redirect to given revision from form if given
117 post_revision = request.POST.get('at_rev', None)
118 post_revision = request.POST.get('at_rev', None)
118 if post_revision:
119 if post_revision:
119 cs = self.__get_cs_or_redirect(post_revision, repo_name)
120 cs = self.__get_cs_or_redirect(post_revision, repo_name)
120 redirect(url('files_home', repo_name=c.repo_name,
121 redirect(url('files_home', repo_name=c.repo_name,
121 revision=cs.raw_id, f_path=f_path))
122 revision=cs.raw_id, f_path=f_path))
122
123
123 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
124 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
124 c.branch = request.GET.get('branch', None)
125 c.branch = request.GET.get('branch', None)
125 c.f_path = f_path
126 c.f_path = f_path
126 c.annotate = annotate
127 c.annotate = annotate
127 cur_rev = c.changeset.revision
128 cur_rev = c.changeset.revision
128
129
129 # prev link
130 # prev link
130 try:
131 try:
131 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
132 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
132 c.url_prev = url('files_home', repo_name=c.repo_name,
133 c.url_prev = url('files_home', repo_name=c.repo_name,
133 revision=prev_rev.raw_id, f_path=f_path)
134 revision=prev_rev.raw_id, f_path=f_path)
134 if c.branch:
135 if c.branch:
135 c.url_prev += '?branch=%s' % c.branch
136 c.url_prev += '?branch=%s' % c.branch
136 except (ChangesetDoesNotExistError, VCSError):
137 except (ChangesetDoesNotExistError, VCSError):
137 c.url_prev = '#'
138 c.url_prev = '#'
138
139
139 # next link
140 # next link
140 try:
141 try:
141 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
142 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
142 c.url_next = url('files_home', repo_name=c.repo_name,
143 c.url_next = url('files_home', repo_name=c.repo_name,
143 revision=next_rev.raw_id, f_path=f_path)
144 revision=next_rev.raw_id, f_path=f_path)
144 if c.branch:
145 if c.branch:
145 c.url_next += '?branch=%s' % c.branch
146 c.url_next += '?branch=%s' % c.branch
146 except (ChangesetDoesNotExistError, VCSError):
147 except (ChangesetDoesNotExistError, VCSError):
147 c.url_next = '#'
148 c.url_next = '#'
148
149
149 # files or dirs
150 # files or dirs
150 try:
151 try:
151 c.file = c.changeset.get_node(f_path)
152 c.file = c.changeset.get_node(f_path)
152
153
153 if c.file.is_file():
154 if c.file.is_file():
154 c.file_history = self._get_node_history(c.changeset, f_path)
155 c.file_history = self._get_node_history(c.changeset, f_path)
155 else:
156 else:
156 c.file_history = []
157 c.file_history = []
157 except RepositoryError, e:
158 except RepositoryError, e:
158 h.flash(str(e), category='warning')
159 h.flash(str(e), category='warning')
159 redirect(h.url('files_home', repo_name=repo_name,
160 redirect(h.url('files_home', repo_name=repo_name,
160 revision=revision))
161 revision=revision))
161
162
162 return render('files/files.html')
163 return render('files/files.html')
163
164
164 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
165 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
165 'repository.admin')
166 'repository.admin')
166 def rawfile(self, repo_name, revision, f_path):
167 def rawfile(self, repo_name, revision, f_path):
167 cs = self.__get_cs_or_redirect(revision, repo_name)
168 cs = self.__get_cs_or_redirect(revision, repo_name)
168 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
169 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
169
170
170 response.content_disposition = 'attachment; filename=%s' % \
171 response.content_disposition = 'attachment; filename=%s' % \
171 safe_str(f_path.split(os.sep)[-1])
172 safe_str(f_path.split(Repository.url_sep())[-1])
172
173
173 response.content_type = file_node.mimetype
174 response.content_type = file_node.mimetype
174 return file_node.content
175 return file_node.content
175
176
176 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
177 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
177 'repository.admin')
178 'repository.admin')
178 def raw(self, repo_name, revision, f_path):
179 def raw(self, repo_name, revision, f_path):
179 cs = self.__get_cs_or_redirect(revision, repo_name)
180 cs = self.__get_cs_or_redirect(revision, repo_name)
180 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
181 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
181
182
182 raw_mimetype_mapping = {
183 raw_mimetype_mapping = {
183 # map original mimetype to a mimetype used for "show as raw"
184 # map original mimetype to a mimetype used for "show as raw"
184 # you can also provide a content-disposition to override the
185 # you can also provide a content-disposition to override the
185 # default "attachment" disposition.
186 # default "attachment" disposition.
186 # orig_type: (new_type, new_dispo)
187 # orig_type: (new_type, new_dispo)
187
188
188 # show images inline:
189 # show images inline:
189 'image/x-icon': ('image/x-icon', 'inline'),
190 'image/x-icon': ('image/x-icon', 'inline'),
190 'image/png': ('image/png', 'inline'),
191 'image/png': ('image/png', 'inline'),
191 'image/gif': ('image/gif', 'inline'),
192 'image/gif': ('image/gif', 'inline'),
192 'image/jpeg': ('image/jpeg', 'inline'),
193 'image/jpeg': ('image/jpeg', 'inline'),
193 'image/svg+xml': ('image/svg+xml', 'inline'),
194 'image/svg+xml': ('image/svg+xml', 'inline'),
194 }
195 }
195
196
196 mimetype = file_node.mimetype
197 mimetype = file_node.mimetype
197 try:
198 try:
198 mimetype, dispo = raw_mimetype_mapping[mimetype]
199 mimetype, dispo = raw_mimetype_mapping[mimetype]
199 except KeyError:
200 except KeyError:
200 # we don't know anything special about this, handle it safely
201 # we don't know anything special about this, handle it safely
201 if file_node.is_binary:
202 if file_node.is_binary:
202 # do same as download raw for binary files
203 # do same as download raw for binary files
203 mimetype, dispo = 'application/octet-stream', 'attachment'
204 mimetype, dispo = 'application/octet-stream', 'attachment'
204 else:
205 else:
205 # do not just use the original mimetype, but force text/plain,
206 # do not just use the original mimetype, but force text/plain,
206 # otherwise it would serve text/html and that might be unsafe.
207 # otherwise it would serve text/html and that might be unsafe.
207 # Note: underlying vcs library fakes text/plain mimetype if the
208 # Note: underlying vcs library fakes text/plain mimetype if the
208 # mimetype can not be determined and it thinks it is not
209 # mimetype can not be determined and it thinks it is not
209 # binary.This might lead to erroneous text display in some
210 # binary.This might lead to erroneous text display in some
210 # cases, but helps in other cases, like with text files
211 # cases, but helps in other cases, like with text files
211 # without extension.
212 # without extension.
212 mimetype, dispo = 'text/plain', 'inline'
213 mimetype, dispo = 'text/plain', 'inline'
213
214
214 if dispo == 'attachment':
215 if dispo == 'attachment':
215 dispo = 'attachment; filename=%s' % \
216 dispo = 'attachment; filename=%s' % \
216 safe_str(f_path.split(os.sep)[-1])
217 safe_str(f_path.split(os.sep)[-1])
217
218
218 response.content_disposition = dispo
219 response.content_disposition = dispo
219 response.content_type = mimetype
220 response.content_type = mimetype
220 return file_node.content
221 return file_node.content
221
222
222 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
223 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
223 def edit(self, repo_name, revision, f_path):
224 def edit(self, repo_name, revision, f_path):
224 r_post = request.POST
225 r_post = request.POST
225
226
226 c.cs = self.__get_cs_or_redirect(revision, repo_name)
227 c.cs = self.__get_cs_or_redirect(revision, repo_name)
227 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
228 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
228
229
229 if c.file.is_binary:
230 if c.file.is_binary:
230 return redirect(url('files_home', repo_name=c.repo_name,
231 return redirect(url('files_home', repo_name=c.repo_name,
231 revision=c.cs.raw_id, f_path=f_path))
232 revision=c.cs.raw_id, f_path=f_path))
232
233
233 c.f_path = f_path
234 c.f_path = f_path
234
235
235 if r_post:
236 if r_post:
236
237
237 old_content = c.file.content
238 old_content = c.file.content
238 sl = old_content.splitlines(1)
239 sl = old_content.splitlines(1)
239 first_line = sl[0] if sl else ''
240 first_line = sl[0] if sl else ''
240 # modes: 0 - Unix, 1 - Mac, 2 - DOS
241 # modes: 0 - Unix, 1 - Mac, 2 - DOS
241 mode = detect_mode(first_line, 0)
242 mode = detect_mode(first_line, 0)
242 content = convert_line_endings(r_post.get('content'), mode)
243 content = convert_line_endings(r_post.get('content'), mode)
243
244
244 message = r_post.get('message') or (_('Edited %s via RhodeCode')
245 message = r_post.get('message') or (_('Edited %s via RhodeCode')
245 % (f_path))
246 % (f_path))
246 author = self.rhodecode_user.full_contact
247 author = self.rhodecode_user.full_contact
247
248
248 if content == old_content:
249 if content == old_content:
249 h.flash(_('No changes'),
250 h.flash(_('No changes'),
250 category='warning')
251 category='warning')
251 return redirect(url('changeset_home', repo_name=c.repo_name,
252 return redirect(url('changeset_home', repo_name=c.repo_name,
252 revision='tip'))
253 revision='tip'))
253
254
254 try:
255 try:
255 self.scm_model.commit_change(repo=c.rhodecode_repo,
256 self.scm_model.commit_change(repo=c.rhodecode_repo,
256 repo_name=repo_name, cs=c.cs,
257 repo_name=repo_name, cs=c.cs,
257 user=self.rhodecode_user,
258 user=self.rhodecode_user,
258 author=author, message=message,
259 author=author, message=message,
259 content=content, f_path=f_path)
260 content=content, f_path=f_path)
260 h.flash(_('Successfully committed to %s' % f_path),
261 h.flash(_('Successfully committed to %s' % f_path),
261 category='success')
262 category='success')
262
263
263 except Exception:
264 except Exception:
264 log.error(traceback.format_exc())
265 log.error(traceback.format_exc())
265 h.flash(_('Error occurred during commit'), category='error')
266 h.flash(_('Error occurred during commit'), category='error')
266 return redirect(url('changeset_home',
267 return redirect(url('changeset_home',
267 repo_name=c.repo_name, revision='tip'))
268 repo_name=c.repo_name, revision='tip'))
268
269
269 return render('files/files_edit.html')
270 return render('files/files_edit.html')
270
271
271 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
272 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
272 def add(self, repo_name, revision, f_path):
273 def add(self, repo_name, revision, f_path):
273 r_post = request.POST
274 r_post = request.POST
274 c.cs = self.__get_cs_or_redirect(revision, repo_name,
275 c.cs = self.__get_cs_or_redirect(revision, repo_name,
275 redirect_after=False)
276 redirect_after=False)
276 if c.cs is None:
277 if c.cs is None:
277 c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias)
278 c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias)
278
279
279 c.f_path = f_path
280 c.f_path = f_path
280
281
281 if r_post:
282 if r_post:
282 unix_mode = 0
283 unix_mode = 0
283 content = convert_line_endings(r_post.get('content'), unix_mode)
284 content = convert_line_endings(r_post.get('content'), unix_mode)
284
285
285 message = r_post.get('message') or (_('Added %s via RhodeCode')
286 message = r_post.get('message') or (_('Added %s via RhodeCode')
286 % (f_path))
287 % (f_path))
287 location = r_post.get('location')
288 location = r_post.get('location')
288 filename = r_post.get('filename')
289 filename = r_post.get('filename')
289 file_obj = r_post.get('upload_file', None)
290 file_obj = r_post.get('upload_file', None)
290
291
291 if file_obj is not None and hasattr(file_obj, 'filename'):
292 if file_obj is not None and hasattr(file_obj, 'filename'):
292 filename = file_obj.filename
293 filename = file_obj.filename
293 content = file_obj.file
294 content = file_obj.file
294
295
295 node_path = os.path.join(location, filename)
296 node_path = os.path.join(location, filename)
296 author = self.rhodecode_user.full_contact
297 author = self.rhodecode_user.full_contact
297
298
298 if not content:
299 if not content:
299 h.flash(_('No content'), category='warning')
300 h.flash(_('No content'), category='warning')
300 return redirect(url('changeset_home', repo_name=c.repo_name,
301 return redirect(url('changeset_home', repo_name=c.repo_name,
301 revision='tip'))
302 revision='tip'))
302 if not filename:
303 if not filename:
303 h.flash(_('No filename'), category='warning')
304 h.flash(_('No filename'), category='warning')
304 return redirect(url('changeset_home', repo_name=c.repo_name,
305 return redirect(url('changeset_home', repo_name=c.repo_name,
305 revision='tip'))
306 revision='tip'))
306
307
307 try:
308 try:
308 self.scm_model.create_node(repo=c.rhodecode_repo,
309 self.scm_model.create_node(repo=c.rhodecode_repo,
309 repo_name=repo_name, cs=c.cs,
310 repo_name=repo_name, cs=c.cs,
310 user=self.rhodecode_user,
311 user=self.rhodecode_user,
311 author=author, message=message,
312 author=author, message=message,
312 content=content, f_path=node_path)
313 content=content, f_path=node_path)
313 h.flash(_('Successfully committed to %s' % node_path),
314 h.flash(_('Successfully committed to %s' % node_path),
314 category='success')
315 category='success')
315 except NodeAlreadyExistsError, e:
316 except NodeAlreadyExistsError, e:
316 h.flash(_(e), category='error')
317 h.flash(_(e), category='error')
317 except Exception:
318 except Exception:
318 log.error(traceback.format_exc())
319 log.error(traceback.format_exc())
319 h.flash(_('Error occurred during commit'), category='error')
320 h.flash(_('Error occurred during commit'), category='error')
320 return redirect(url('changeset_home',
321 return redirect(url('changeset_home',
321 repo_name=c.repo_name, revision='tip'))
322 repo_name=c.repo_name, revision='tip'))
322
323
323 return render('files/files_add.html')
324 return render('files/files_add.html')
324
325
325 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
326 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
326 'repository.admin')
327 'repository.admin')
327 def archivefile(self, repo_name, fname):
328 def archivefile(self, repo_name, fname):
328
329
329 fileformat = None
330 fileformat = None
330 revision = None
331 revision = None
331 ext = None
332 ext = None
332 subrepos = request.GET.get('subrepos') == 'true'
333 subrepos = request.GET.get('subrepos') == 'true'
333
334
334 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
335 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
335 archive_spec = fname.split(ext_data[1])
336 archive_spec = fname.split(ext_data[1])
336 if len(archive_spec) == 2 and archive_spec[1] == '':
337 if len(archive_spec) == 2 and archive_spec[1] == '':
337 fileformat = a_type or ext_data[1]
338 fileformat = a_type or ext_data[1]
338 revision = archive_spec[0]
339 revision = archive_spec[0]
339 ext = ext_data[1]
340 ext = ext_data[1]
340
341
341 try:
342 try:
342 dbrepo = RepoModel().get_by_repo_name(repo_name)
343 dbrepo = RepoModel().get_by_repo_name(repo_name)
343 if dbrepo.enable_downloads is False:
344 if dbrepo.enable_downloads is False:
344 return _('downloads disabled')
345 return _('downloads disabled')
345
346
346 if c.rhodecode_repo.alias == 'hg':
347 if c.rhodecode_repo.alias == 'hg':
347 # patch and reset hooks section of UI config to not run any
348 # patch and reset hooks section of UI config to not run any
348 # hooks on fetching archives with subrepos
349 # hooks on fetching archives with subrepos
349 for k, v in c.rhodecode_repo._repo.ui.configitems('hooks'):
350 for k, v in c.rhodecode_repo._repo.ui.configitems('hooks'):
350 c.rhodecode_repo._repo.ui.setconfig('hooks', k, None)
351 c.rhodecode_repo._repo.ui.setconfig('hooks', k, None)
351
352
352 cs = c.rhodecode_repo.get_changeset(revision)
353 cs = c.rhodecode_repo.get_changeset(revision)
353 content_type = settings.ARCHIVE_SPECS[fileformat][0]
354 content_type = settings.ARCHIVE_SPECS[fileformat][0]
354 except ChangesetDoesNotExistError:
355 except ChangesetDoesNotExistError:
355 return _('Unknown revision %s') % revision
356 return _('Unknown revision %s') % revision
356 except EmptyRepositoryError:
357 except EmptyRepositoryError:
357 return _('Empty repository')
358 return _('Empty repository')
358 except (ImproperArchiveTypeError, KeyError):
359 except (ImproperArchiveTypeError, KeyError):
359 return _('Unknown archive type')
360 return _('Unknown archive type')
360
361
361 response.content_type = content_type
362 response.content_type = content_type
362 response.content_disposition = 'attachment; filename=%s-%s%s' \
363 response.content_disposition = 'attachment; filename=%s-%s%s' \
363 % (repo_name, revision, ext)
364 % (repo_name, revision, ext)
364
365
365 import tempfile
366 import tempfile
366 archive = tempfile.mkstemp()[1]
367 archive = tempfile.mkstemp()[1]
367 t = open(archive, 'wb')
368 t = open(archive, 'wb')
368 cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
369 cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
369
370
370 def get_chunked_archive(archive):
371 def get_chunked_archive(archive):
371 stream = open(archive, 'rb')
372 stream = open(archive, 'rb')
372 while True:
373 while True:
373 data = stream.read(4096)
374 data = stream.read(4096)
374 if not data:
375 if not data:
375 os.remove(archive)
376 os.remove(archive)
376 break
377 break
377 yield data
378 yield data
378
379
379 return get_chunked_archive(archive)
380 return get_chunked_archive(archive)
380
381
381 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
382 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
382 'repository.admin')
383 'repository.admin')
383 def diff(self, repo_name, f_path):
384 def diff(self, repo_name, f_path):
384 ignore_whitespace = request.GET.get('ignorews') == '1'
385 ignore_whitespace = request.GET.get('ignorews') == '1'
385 line_context = request.GET.get('context', 3)
386 line_context = request.GET.get('context', 3)
386 diff1 = request.GET.get('diff1', '')
387 diff1 = request.GET.get('diff1', '')
387 diff2 = request.GET.get('diff2', '')
388 diff2 = request.GET.get('diff2', '')
388 c.action = request.GET.get('diff')
389 c.action = request.GET.get('diff')
389 c.no_changes = diff1 == diff2
390 c.no_changes = diff1 == diff2
390 c.f_path = f_path
391 c.f_path = f_path
391 c.big_diff = False
392 c.big_diff = False
392 c.anchor_url = anchor_url
393 c.anchor_url = anchor_url
393 c.ignorews_url = _ignorews_url
394 c.ignorews_url = _ignorews_url
394 c.context_url = _context_url
395 c.context_url = _context_url
395 c.changes = OrderedDict()
396 c.changes = OrderedDict()
396 c.changes[diff2] = []
397 c.changes[diff2] = []
397 try:
398 try:
398 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
399 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
399 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
400 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
400 node1 = c.changeset_1.get_node(f_path)
401 node1 = c.changeset_1.get_node(f_path)
401 else:
402 else:
402 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
403 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
403 node1 = FileNode('.', '', changeset=c.changeset_1)
404 node1 = FileNode('.', '', changeset=c.changeset_1)
404
405
405 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
406 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
406 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
407 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
407 node2 = c.changeset_2.get_node(f_path)
408 node2 = c.changeset_2.get_node(f_path)
408 else:
409 else:
409 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
410 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
410 node2 = FileNode('.', '', changeset=c.changeset_2)
411 node2 = FileNode('.', '', changeset=c.changeset_2)
411 except RepositoryError:
412 except RepositoryError:
412 return redirect(url('files_home', repo_name=c.repo_name,
413 return redirect(url('files_home', repo_name=c.repo_name,
413 f_path=f_path))
414 f_path=f_path))
414
415
415 if c.action == 'download':
416 if c.action == 'download':
416 _diff = diffs.get_gitdiff(node1, node2,
417 _diff = diffs.get_gitdiff(node1, node2,
417 ignore_whitespace=ignore_whitespace,
418 ignore_whitespace=ignore_whitespace,
418 context=line_context)
419 context=line_context)
419 diff = diffs.DiffProcessor(_diff, format='gitdiff')
420 diff = diffs.DiffProcessor(_diff, format='gitdiff')
420
421
421 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
422 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
422 response.content_type = 'text/plain'
423 response.content_type = 'text/plain'
423 response.content_disposition = (
424 response.content_disposition = (
424 'attachment; filename=%s' % diff_name
425 'attachment; filename=%s' % diff_name
425 )
426 )
426 return diff.raw_diff()
427 return diff.raw_diff()
427
428
428 elif c.action == 'raw':
429 elif c.action == 'raw':
429 _diff = diffs.get_gitdiff(node1, node2,
430 _diff = diffs.get_gitdiff(node1, node2,
430 ignore_whitespace=ignore_whitespace,
431 ignore_whitespace=ignore_whitespace,
431 context=line_context)
432 context=line_context)
432 diff = diffs.DiffProcessor(_diff, format='gitdiff')
433 diff = diffs.DiffProcessor(_diff, format='gitdiff')
433 response.content_type = 'text/plain'
434 response.content_type = 'text/plain'
434 return diff.raw_diff()
435 return diff.raw_diff()
435
436
436 else:
437 else:
437 fid = h.FID(diff2, node2.path)
438 fid = h.FID(diff2, node2.path)
438 line_context_lcl = get_line_ctx(fid, request.GET)
439 line_context_lcl = get_line_ctx(fid, request.GET)
439 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
440 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
440
441
441 lim = request.GET.get('fulldiff') or self.cut_off_limit
442 lim = request.GET.get('fulldiff') or self.cut_off_limit
442 _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1,
443 _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1,
443 filenode_new=node2,
444 filenode_new=node2,
444 cut_off_limit=lim,
445 cut_off_limit=lim,
445 ignore_whitespace=ign_whitespace_lcl,
446 ignore_whitespace=ign_whitespace_lcl,
446 line_context=line_context_lcl,
447 line_context=line_context_lcl,
447 enable_comments=False)
448 enable_comments=False)
448
449
449 c.changes = [('', node2, diff, cs1, cs2, st,)]
450 c.changes = [('', node2, diff, cs1, cs2, st,)]
450
451
451 return render('files/file_diff.html')
452 return render('files/file_diff.html')
452
453
453 def _get_node_history(self, cs, f_path):
454 def _get_node_history(self, cs, f_path):
454 changesets = cs.get_file_history(f_path)
455 changesets = cs.get_file_history(f_path)
455 hist_l = []
456 hist_l = []
456
457
457 changesets_group = ([], _("Changesets"))
458 changesets_group = ([], _("Changesets"))
458 branches_group = ([], _("Branches"))
459 branches_group = ([], _("Branches"))
459 tags_group = ([], _("Tags"))
460 tags_group = ([], _("Tags"))
460 _hg = cs.repository.alias == 'hg'
461 _hg = cs.repository.alias == 'hg'
461 for chs in changesets:
462 for chs in changesets:
462 _branch = '(%s)' % chs.branch if _hg else ''
463 _branch = '(%s)' % chs.branch if _hg else ''
463 n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch)
464 n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch)
464 changesets_group[0].append((chs.raw_id, n_desc,))
465 changesets_group[0].append((chs.raw_id, n_desc,))
465
466
466 hist_l.append(changesets_group)
467 hist_l.append(changesets_group)
467
468
468 for name, chs in c.rhodecode_repo.branches.items():
469 for name, chs in c.rhodecode_repo.branches.items():
469 branches_group[0].append((chs, name),)
470 branches_group[0].append((chs, name),)
470 hist_l.append(branches_group)
471 hist_l.append(branches_group)
471
472
472 for name, chs in c.rhodecode_repo.tags.items():
473 for name, chs in c.rhodecode_repo.tags.items():
473 tags_group[0].append((chs, name),)
474 tags_group[0].append((chs, name),)
474 hist_l.append(tags_group)
475 hist_l.append(tags_group)
475
476
476 return hist_l
477 return hist_l
477
478
478 @jsonify
479 @jsonify
479 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
480 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
480 'repository.admin')
481 'repository.admin')
481 def nodelist(self, repo_name, revision, f_path):
482 def nodelist(self, repo_name, revision, f_path):
482 if request.environ.get('HTTP_X_PARTIAL_XHR'):
483 if request.environ.get('HTTP_X_PARTIAL_XHR'):
483 cs = self.__get_cs_or_redirect(revision, repo_name)
484 cs = self.__get_cs_or_redirect(revision, repo_name)
484 _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
485 _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
485 flat=False)
486 flat=False)
486 return _d + _f
487 return _d + _f
@@ -1,315 +1,316 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2
2
3 ARCHIVE_SPECS = {
3 ARCHIVE_SPECS = {
4 '.tar.bz2': ('application/x-bzip2', 'tbz2', ''),
4 '.tar.bz2': ('application/x-bzip2', 'tbz2', ''),
5 '.tar.gz': ('application/x-gzip', 'tgz', ''),
5 '.tar.gz': ('application/x-gzip', 'tgz', ''),
6 '.zip': ('application/zip', 'zip', ''),
6 '.zip': ('application/zip', 'zip', ''),
7 }
7 }
8
8
9
9
10 class TestFilesController(TestController):
10 class TestFilesController(TestController):
11
11
12 def test_index(self):
12 def test_index(self):
13 self.log_user()
13 self.log_user()
14 response = self.app.get(url(controller='files', action='index',
14 response = self.app.get(url(controller='files', action='index',
15 repo_name=HG_REPO,
15 repo_name=HG_REPO,
16 revision='tip',
16 revision='tip',
17 f_path='/'))
17 f_path='/'))
18 # Test response...
18 # Test response...
19 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/docs">docs</a>')
19 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/docs">docs</a>')
20 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/tests">tests</a>')
20 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/tests">tests</a>')
21 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/vcs">vcs</a>')
21 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/vcs">vcs</a>')
22 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/.hgignore">.hgignore</a>')
22 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/.hgignore">.hgignore</a>')
23 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/MANIFEST.in">MANIFEST.in</a>')
23 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/MANIFEST.in">MANIFEST.in</a>')
24
24
25 def test_index_revision(self):
25 def test_index_revision(self):
26 self.log_user()
26 self.log_user()
27
27
28 response = self.app.get(
28 response = self.app.get(
29 url(controller='files', action='index',
29 url(controller='files', action='index',
30 repo_name=HG_REPO,
30 repo_name=HG_REPO,
31 revision='7ba66bec8d6dbba14a2155be32408c435c5f4492',
31 revision='7ba66bec8d6dbba14a2155be32408c435c5f4492',
32 f_path='/')
32 f_path='/')
33 )
33 )
34
34
35 #Test response...
35 #Test response...
36
36
37 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs">docs</a>')
37 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs">docs</a>')
38 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests">tests</a>')
38 response.mustcontain('<a class="browser-dir ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests">tests</a>')
39 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/README.rst">README.rst</a>')
39 response.mustcontain('<a class="browser-file ypjax-link" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/README.rst">README.rst</a>')
40 response.mustcontain('1.1 KiB')
40 response.mustcontain('1.1 KiB')
41 response.mustcontain('text/x-python')
41 response.mustcontain('text/x-python')
42
42
43 def test_index_different_branch(self):
43 def test_index_different_branch(self):
44 self.log_user()
44 self.log_user()
45
45
46 response = self.app.get(url(controller='files', action='index',
46 response = self.app.get(url(controller='files', action='index',
47 repo_name=HG_REPO,
47 repo_name=HG_REPO,
48 revision='97e8b885c04894463c51898e14387d80c30ed1ee',
48 revision='97e8b885c04894463c51898e14387d80c30ed1ee',
49 f_path='/'))
49 f_path='/'))
50
50
51 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: git</a></span>""")
51 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: git</a></span>""")
52
52
53 def test_index_paging(self):
53 def test_index_paging(self):
54 self.log_user()
54 self.log_user()
55
55
56 for r in [(73, 'a066b25d5df7016b45a41b7e2a78c33b57adc235'),
56 for r in [(73, 'a066b25d5df7016b45a41b7e2a78c33b57adc235'),
57 (92, 'cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e'),
57 (92, 'cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e'),
58 (109, '75feb4c33e81186c87eac740cee2447330288412'),
58 (109, '75feb4c33e81186c87eac740cee2447330288412'),
59 (1, '3d8f361e72ab303da48d799ff1ac40d5ac37c67e'),
59 (1, '3d8f361e72ab303da48d799ff1ac40d5ac37c67e'),
60 (0, 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]:
60 (0, 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]:
61
61
62 response = self.app.get(url(controller='files', action='index',
62 response = self.app.get(url(controller='files', action='index',
63 repo_name=HG_REPO,
63 repo_name=HG_REPO,
64 revision=r[1],
64 revision=r[1],
65 f_path='/'))
65 f_path='/'))
66
66
67 response.mustcontain("""@ r%s:%s""" % (r[0], r[1][:12]))
67 response.mustcontain("""@ r%s:%s""" % (r[0], r[1][:12]))
68
68
69 def test_file_source(self):
69 def test_file_source(self):
70 self.log_user()
70 self.log_user()
71 response = self.app.get(url(controller='files', action='index',
71 response = self.app.get(url(controller='files', action='index',
72 repo_name=HG_REPO,
72 repo_name=HG_REPO,
73 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
73 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
74 f_path='vcs/nodes.py'))
74 f_path='vcs/nodes.py'))
75
75
76 #test or history
76 #test or history
77 response.mustcontain("""<optgroup label="Changesets">
77 response.mustcontain("""<optgroup label="Changesets">
78 <option value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776 (default)</option>
78 <option value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776 (default)</option>
79 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35 (default)</option>
79 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35 (default)</option>
80 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c (default)</option>
80 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c (default)</option>
81 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329 (default)</option>
81 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329 (default)</option>
82 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf (git)</option>
82 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf (git)</option>
83 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81 (default)</option>
83 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81 (default)</option>
84 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc (default)</option>
84 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc (default)</option>
85 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21 (default)</option>
85 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21 (default)</option>
86 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2 (default)</option>
86 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2 (default)</option>
87 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85 (default)</option>
87 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85 (default)</option>
88 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2 (git)</option>
88 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2 (git)</option>
89 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93 (default)</option>
89 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93 (default)</option>
90 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b (default)</option>
90 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b (default)</option>
91 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455 (default)</option>
91 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455 (default)</option>
92 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32 (default)</option>
92 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32 (default)</option>
93 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0 (default)</option>
93 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0 (default)</option>
94 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081 (default)</option>
94 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081 (default)</option>
95 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad (default)</option>
95 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad (default)</option>
96 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7 (default)</option>
96 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7 (default)</option>
97 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059 (web)</option>
97 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059 (web)</option>
98 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb (web)</option>
98 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb (web)</option>
99 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1 (web)</option>
99 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1 (web)</option>
100 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71 (web)</option>
100 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71 (web)</option>
101 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771 (web)</option>
101 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771 (web)</option>
102 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526 (web)</option>
102 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526 (web)</option>
103 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4 (web)</option>
103 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4 (web)</option>
104 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b (web)</option>
104 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b (web)</option>
105 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c (web)</option>
105 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c (web)</option>
106 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1 (default)</option>
106 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1 (default)</option>
107 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5 (default)</option>
107 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5 (default)</option>
108 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283 (default)</option>
108 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283 (default)</option>
109 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6 (default)</option>
109 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6 (default)</option>
110 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3 (default)</option>
110 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3 (default)</option>
111 </optgroup>
111 </optgroup>
112 <optgroup label="Branches">
112 <optgroup label="Branches">
113 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">default</option>
113 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">default</option>
114 <option value="97e8b885c04894463c51898e14387d80c30ed1ee">git</option>
114 <option value="97e8b885c04894463c51898e14387d80c30ed1ee">git</option>
115 <option value="2e6a2bf9356ca56df08807f4ad86d480da72a8f4">web</option>
115 <option value="2e6a2bf9356ca56df08807f4ad86d480da72a8f4">web</option>
116 </optgroup>
116 </optgroup>
117 <optgroup label="Tags">
117 <optgroup label="Tags">
118 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</option>
118 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</option>
119 <option value="fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</option>
119 <option value="fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</option>
120 <option value="17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</option>
120 <option value="17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</option>
121 <option value="a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</option>
121 <option value="a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</option>
122 <option value="eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</option>
122 <option value="eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</option>
123 </optgroup>
123 </optgroup>
124 """)
124 """)
125
125
126 response.mustcontain("""<div class="commit">merge</div>""")
126 response.mustcontain("""<div class="commit">merge</div>""")
127
127
128 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""")
128 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""")
129
129
130 def test_file_annotation(self):
130 def test_file_annotation(self):
131 self.log_user()
131 self.log_user()
132 response = self.app.get(url(controller='files', action='index',
132 response = self.app.get(url(controller='files', action='index',
133 repo_name=HG_REPO,
133 repo_name=HG_REPO,
134 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
134 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
135 f_path='vcs/nodes.py',
135 f_path='vcs/nodes.py',
136 annotate=True))
136 annotate=True))
137
137
138
138
139 response.mustcontain("""<optgroup label="Changesets">
139 response.mustcontain("""<optgroup label="Changesets">
140 <option value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776 (default)</option>
140 <option value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776 (default)</option>
141 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35 (default)</option>
141 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35 (default)</option>
142 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c (default)</option>
142 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c (default)</option>
143 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329 (default)</option>
143 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329 (default)</option>
144 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf (git)</option>
144 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf (git)</option>
145 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81 (default)</option>
145 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81 (default)</option>
146 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc (default)</option>
146 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc (default)</option>
147 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21 (default)</option>
147 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21 (default)</option>
148 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2 (default)</option>
148 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2 (default)</option>
149 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85 (default)</option>
149 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85 (default)</option>
150 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2 (git)</option>
150 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2 (git)</option>
151 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93 (default)</option>
151 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93 (default)</option>
152 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b (default)</option>
152 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b (default)</option>
153 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455 (default)</option>
153 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455 (default)</option>
154 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32 (default)</option>
154 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32 (default)</option>
155 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0 (default)</option>
155 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0 (default)</option>
156 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081 (default)</option>
156 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081 (default)</option>
157 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad (default)</option>
157 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad (default)</option>
158 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7 (default)</option>
158 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7 (default)</option>
159 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059 (web)</option>
159 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059 (web)</option>
160 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb (web)</option>
160 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb (web)</option>
161 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1 (web)</option>
161 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1 (web)</option>
162 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71 (web)</option>
162 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71 (web)</option>
163 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771 (web)</option>
163 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771 (web)</option>
164 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526 (web)</option>
164 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526 (web)</option>
165 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4 (web)</option>
165 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4 (web)</option>
166 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b (web)</option>
166 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b (web)</option>
167 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c (web)</option>
167 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c (web)</option>
168 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1 (default)</option>
168 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1 (default)</option>
169 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5 (default)</option>
169 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5 (default)</option>
170 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283 (default)</option>
170 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283 (default)</option>
171 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6 (default)</option>
171 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6 (default)</option>
172 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3 (default)</option>
172 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3 (default)</option>
173 </optgroup>
173 </optgroup>
174 <optgroup label="Branches">
174 <optgroup label="Branches">
175 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">default</option>
175 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">default</option>
176 <option value="97e8b885c04894463c51898e14387d80c30ed1ee">git</option>
176 <option value="97e8b885c04894463c51898e14387d80c30ed1ee">git</option>
177 <option value="2e6a2bf9356ca56df08807f4ad86d480da72a8f4">web</option>
177 <option value="2e6a2bf9356ca56df08807f4ad86d480da72a8f4">web</option>
178 </optgroup>
178 </optgroup>
179 <optgroup label="Tags">
179 <optgroup label="Tags">
180 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</option>
180 <option selected="selected" value="27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</option>
181 <option value="fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</option>
181 <option value="fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</option>
182 <option value="17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</option>
182 <option value="17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</option>
183 <option value="a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</option>
183 <option value="a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</option>
184 <option value="eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</option>
184 <option value="eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</option>
185 </optgroup>""")
185 </optgroup>""")
186
186
187 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""")
187 response.mustcontain("""<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""")
188
188
189 def test_archival(self):
189 def test_archival(self):
190 self.log_user()
190 self.log_user()
191
191
192 for arch_ext, info in ARCHIVE_SPECS.items():
192 for arch_ext, info in ARCHIVE_SPECS.items():
193 fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
193 fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
194 filename = '%s-%s' % (HG_REPO, fname)
194 filename = '%s-%s' % (HG_REPO, fname)
195
195
196 response = self.app.get(url(controller='files', action='archivefile',
196 response = self.app.get(url(controller='files', action='archivefile',
197 repo_name=HG_REPO,
197 repo_name=HG_REPO,
198 fname=fname))
198 fname=fname))
199
199
200 assert response.status == '200 OK', 'wrong response code'
200 self.assertEqual(response.status, '200 OK')
201 assert response.response._headers.items() == [('Pragma', 'no-cache'),
201 self.assertEqual(response.response._headers.items(),
202 [('Pragma', 'no-cache'),
202 ('Cache-Control', 'no-cache'),
203 ('Cache-Control', 'no-cache'),
203 ('Content-Type', '%s; charset=utf-8' % info[0]),
204 ('Content-Type', '%s; charset=utf-8' % info[0]),
204 ('Content-Disposition', 'attachment; filename=%s' % filename), ], 'wrong headers'
205 ('Content-Disposition', 'attachment; filename=%s' % filename),]
206 )
205
207
206 def test_archival_wrong_ext(self):
208 def test_archival_wrong_ext(self):
207 self.log_user()
209 self.log_user()
208
210
209 for arch_ext in ['tar', 'rar', 'x', '..ax', '.zipz']:
211 for arch_ext in ['tar', 'rar', 'x', '..ax', '.zipz']:
210 fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
212 fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
211
213
212 response = self.app.get(url(controller='files', action='archivefile',
214 response = self.app.get(url(controller='files', action='archivefile',
213 repo_name=HG_REPO,
215 repo_name=HG_REPO,
214 fname=fname))
216 fname=fname))
215 assert 'Unknown archive type' in response.body
217 response.mustcontain('Unknown archive type')
216
217
218
218 def test_archival_wrong_revision(self):
219 def test_archival_wrong_revision(self):
219 self.log_user()
220 self.log_user()
220
221
221 for rev in ['00x000000', 'tar', 'wrong', '@##$@$424213232', '232dffcd']:
222 for rev in ['00x000000', 'tar', 'wrong', '@##$@$424213232', '232dffcd']:
222 fname = '%s.zip' % rev
223 fname = '%s.zip' % rev
223
224
224 response = self.app.get(url(controller='files', action='archivefile',
225 response = self.app.get(url(controller='files', action='archivefile',
225 repo_name=HG_REPO,
226 repo_name=HG_REPO,
226 fname=fname))
227 fname=fname))
227 assert 'Unknown revision' in response.body
228 response.mustcontain('Unknown revision')
228
229
229 #==========================================================================
230 #==========================================================================
230 # RAW FILE
231 # RAW FILE
231 #==========================================================================
232 #==========================================================================
232 def test_raw_file_ok(self):
233 def test_raw_file_ok(self):
233 self.log_user()
234 self.log_user()
234 response = self.app.get(url(controller='files', action='rawfile',
235 response = self.app.get(url(controller='files', action='rawfile',
235 repo_name=HG_REPO,
236 repo_name=HG_REPO,
236 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
237 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
237 f_path='vcs/nodes.py'))
238 f_path='vcs/nodes.py'))
238
239
239 assert response.content_disposition == "attachment; filename=nodes.py"
240 self.assertEqual(response.content_disposition, "attachment; filename=nodes.py")
240 assert response.content_type == "text/x-python"
241 self.assertEqual(response.content_type, "text/x-python")
241
242
242 def test_raw_file_wrong_cs(self):
243 def test_raw_file_wrong_cs(self):
243 self.log_user()
244 self.log_user()
244 rev = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
245 rev = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
245 f_path = 'vcs/nodes.py'
246 f_path = 'vcs/nodes.py'
246
247
247 response = self.app.get(url(controller='files', action='rawfile',
248 response = self.app.get(url(controller='files', action='rawfile',
248 repo_name=HG_REPO,
249 repo_name=HG_REPO,
249 revision=rev,
250 revision=rev,
250 f_path=f_path))
251 f_path=f_path))
251
252
252 msg = """Revision %r does not exist for this repository""" % (rev)
253 msg = """Revision %r does not exist for this repository""" % (rev)
253 self.checkSessionFlash(response, msg)
254 self.checkSessionFlash(response, msg)
254
255
255 msg = """%s""" % (HG_REPO)
256 msg = """%s""" % (HG_REPO)
256 self.checkSessionFlash(response, msg)
257 self.checkSessionFlash(response, msg)
257
258
258 def test_raw_file_wrong_f_path(self):
259 def test_raw_file_wrong_f_path(self):
259 self.log_user()
260 self.log_user()
260 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
261 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
261 f_path = 'vcs/ERRORnodes.py'
262 f_path = 'vcs/ERRORnodes.py'
262 response = self.app.get(url(controller='files', action='rawfile',
263 response = self.app.get(url(controller='files', action='rawfile',
263 repo_name=HG_REPO,
264 repo_name=HG_REPO,
264 revision=rev,
265 revision=rev,
265 f_path=f_path))
266 f_path=f_path))
266
267
267 msg = "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12])
268 msg = "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12])
268 self.checkSessionFlash(response, msg)
269 self.checkSessionFlash(response, msg)
269
270
270 #==========================================================================
271 #==========================================================================
271 # RAW RESPONSE - PLAIN
272 # RAW RESPONSE - PLAIN
272 #==========================================================================
273 #==========================================================================
273 def test_raw_ok(self):
274 def test_raw_ok(self):
274 self.log_user()
275 self.log_user()
275 response = self.app.get(url(controller='files', action='raw',
276 response = self.app.get(url(controller='files', action='raw',
276 repo_name=HG_REPO,
277 repo_name=HG_REPO,
277 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
278 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
278 f_path='vcs/nodes.py'))
279 f_path='vcs/nodes.py'))
279
280
280 assert response.content_type == "text/plain"
281 self.assertEqual(response.content_type, "text/plain")
281
282
282 def test_raw_wrong_cs(self):
283 def test_raw_wrong_cs(self):
283 self.log_user()
284 self.log_user()
284 rev = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
285 rev = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
285 f_path = 'vcs/nodes.py'
286 f_path = 'vcs/nodes.py'
286
287
287 response = self.app.get(url(controller='files', action='raw',
288 response = self.app.get(url(controller='files', action='raw',
288 repo_name=HG_REPO,
289 repo_name=HG_REPO,
289 revision=rev,
290 revision=rev,
290 f_path=f_path))
291 f_path=f_path))
291 msg = """Revision %r does not exist for this repository""" % (rev)
292 msg = """Revision %r does not exist for this repository""" % (rev)
292 self.checkSessionFlash(response, msg)
293 self.checkSessionFlash(response, msg)
293
294
294 msg = """%s""" % (HG_REPO)
295 msg = """%s""" % (HG_REPO)
295 self.checkSessionFlash(response, msg)
296 self.checkSessionFlash(response, msg)
296
297
297 def test_raw_wrong_f_path(self):
298 def test_raw_wrong_f_path(self):
298 self.log_user()
299 self.log_user()
299 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
300 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
300 f_path = 'vcs/ERRORnodes.py'
301 f_path = 'vcs/ERRORnodes.py'
301 response = self.app.get(url(controller='files', action='raw',
302 response = self.app.get(url(controller='files', action='raw',
302 repo_name=HG_REPO,
303 repo_name=HG_REPO,
303 revision=rev,
304 revision=rev,
304 f_path=f_path))
305 f_path=f_path))
305 msg = "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12])
306 msg = "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12])
306 self.checkSessionFlash(response, msg)
307 self.checkSessionFlash(response, msg)
307
308
308 def test_ajaxed_files_list(self):
309 def test_ajaxed_files_list(self):
309 self.log_user()
310 self.log_user()
310 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
311 rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
311 response = self.app.get(
312 response = self.app.get(
312 url('files_nodelist_home', repo_name=HG_REPO,f_path='/',revision=rev),
313 url('files_nodelist_home', repo_name=HG_REPO,f_path='/',revision=rev),
313 extra_environ={'HTTP_X_PARTIAL_XHR': '1'},
314 extra_environ={'HTTP_X_PARTIAL_XHR': '1'},
314 )
315 )
315 response.mustcontain("vcs/web/simplevcs/views/repository.py")
316 response.mustcontain("vcs/web/simplevcs/views/repository.py")
@@ -1,715 +1,715 b''
1 import os
1 import os
2 import unittest
2 import unittest
3 from rhodecode.tests import *
3 from rhodecode.tests import *
4
4
5 from rhodecode.model.repos_group import ReposGroupModel
5 from rhodecode.model.repos_group import ReposGroupModel
6 from rhodecode.model.repo import RepoModel
6 from rhodecode.model.repo import RepoModel
7 from rhodecode.model.db import RepoGroup, User, Notification, UserNotification, \
7 from rhodecode.model.db import RepoGroup, User, Notification, UserNotification, \
8 UsersGroup, UsersGroupMember, Permission, UsersGroupRepoGroupToPerm
8 UsersGroup, UsersGroupMember, Permission, UsersGroupRepoGroupToPerm,\
9 Repository
9 from sqlalchemy.exc import IntegrityError
10 from sqlalchemy.exc import IntegrityError
10 from rhodecode.model.user import UserModel
11 from rhodecode.model.user import UserModel
11
12
12 from rhodecode.model.meta import Session
13 from rhodecode.model.meta import Session
13 from rhodecode.model.notification import NotificationModel
14 from rhodecode.model.notification import NotificationModel
14 from rhodecode.model.users_group import UsersGroupModel
15 from rhodecode.model.users_group import UsersGroupModel
15 from rhodecode.lib.auth import AuthUser
16 from rhodecode.lib.auth import AuthUser
16
17
17
18
18 def _make_group(path, desc='desc', parent_id=None,
19 def _make_group(path, desc='desc', parent_id=None,
19 skip_if_exists=False):
20 skip_if_exists=False):
20
21
21 gr = RepoGroup.get_by_group_name(path)
22 gr = RepoGroup.get_by_group_name(path)
22 if gr and skip_if_exists:
23 if gr and skip_if_exists:
23 return gr
24 return gr
24
25
25 gr = ReposGroupModel().create(path, desc, parent_id)
26 gr = ReposGroupModel().create(path, desc, parent_id)
26 return gr
27 return gr
27
28
28
29
29 class TestReposGroups(unittest.TestCase):
30 class TestReposGroups(unittest.TestCase):
30
31
31 def setUp(self):
32 def setUp(self):
32 self.g1 = _make_group('test1', skip_if_exists=True)
33 self.g1 = _make_group('test1', skip_if_exists=True)
33 Session.commit()
34 Session.commit()
34 self.g2 = _make_group('test2', skip_if_exists=True)
35 self.g2 = _make_group('test2', skip_if_exists=True)
35 Session.commit()
36 Session.commit()
36 self.g3 = _make_group('test3', skip_if_exists=True)
37 self.g3 = _make_group('test3', skip_if_exists=True)
37 Session.commit()
38 Session.commit()
38
39
39 def tearDown(self):
40 def tearDown(self):
40 print 'out'
41 print 'out'
41
42
42 def __check_path(self, *path):
43 def __check_path(self, *path):
43 """
44 """
44 Checks the path for existance !
45 Checks the path for existance !
45 """
46 """
46 path = [TESTS_TMP_PATH] + list(path)
47 path = [TESTS_TMP_PATH] + list(path)
47 path = os.path.join(*path)
48 path = os.path.join(*path)
48 return os.path.isdir(path)
49 return os.path.isdir(path)
49
50
50 def _check_folders(self):
51 def _check_folders(self):
51 print os.listdir(TESTS_TMP_PATH)
52 print os.listdir(TESTS_TMP_PATH)
52
53
53 def __delete_group(self, id_):
54 def __delete_group(self, id_):
54 ReposGroupModel().delete(id_)
55 ReposGroupModel().delete(id_)
55
56
56 def __update_group(self, id_, path, desc='desc', parent_id=None):
57 def __update_group(self, id_, path, desc='desc', parent_id=None):
57 form_data = dict(
58 form_data = dict(
58 group_name=path,
59 group_name=path,
59 group_description=desc,
60 group_description=desc,
60 group_parent_id=parent_id,
61 group_parent_id=parent_id,
61 perms_updates=[],
62 perms_updates=[],
62 perms_new=[]
63 perms_new=[]
63 )
64 )
64 gr = ReposGroupModel().update(id_, form_data)
65 gr = ReposGroupModel().update(id_, form_data)
65 return gr
66 return gr
66
67
67 def test_create_group(self):
68 def test_create_group(self):
68 g = _make_group('newGroup')
69 g = _make_group('newGroup')
69 self.assertEqual(g.full_path, 'newGroup')
70 self.assertEqual(g.full_path, 'newGroup')
70
71
71 self.assertTrue(self.__check_path('newGroup'))
72 self.assertTrue(self.__check_path('newGroup'))
72
73
73 def test_create_same_name_group(self):
74 def test_create_same_name_group(self):
74 self.assertRaises(IntegrityError, lambda:_make_group('newGroup'))
75 self.assertRaises(IntegrityError, lambda:_make_group('newGroup'))
75 Session.rollback()
76 Session.rollback()
76
77
77 def test_same_subgroup(self):
78 def test_same_subgroup(self):
78 sg1 = _make_group('sub1', parent_id=self.g1.group_id)
79 sg1 = _make_group('sub1', parent_id=self.g1.group_id)
79 self.assertEqual(sg1.parent_group, self.g1)
80 self.assertEqual(sg1.parent_group, self.g1)
80 self.assertEqual(sg1.full_path, 'test1/sub1')
81 self.assertEqual(sg1.full_path, 'test1/sub1')
81 self.assertTrue(self.__check_path('test1', 'sub1'))
82 self.assertTrue(self.__check_path('test1', 'sub1'))
82
83
83 ssg1 = _make_group('subsub1', parent_id=sg1.group_id)
84 ssg1 = _make_group('subsub1', parent_id=sg1.group_id)
84 self.assertEqual(ssg1.parent_group, sg1)
85 self.assertEqual(ssg1.parent_group, sg1)
85 self.assertEqual(ssg1.full_path, 'test1/sub1/subsub1')
86 self.assertEqual(ssg1.full_path, 'test1/sub1/subsub1')
86 self.assertTrue(self.__check_path('test1', 'sub1', 'subsub1'))
87 self.assertTrue(self.__check_path('test1', 'sub1', 'subsub1'))
87
88
88 def test_remove_group(self):
89 def test_remove_group(self):
89 sg1 = _make_group('deleteme')
90 sg1 = _make_group('deleteme')
90 self.__delete_group(sg1.group_id)
91 self.__delete_group(sg1.group_id)
91
92
92 self.assertEqual(RepoGroup.get(sg1.group_id), None)
93 self.assertEqual(RepoGroup.get(sg1.group_id), None)
93 self.assertFalse(self.__check_path('deteteme'))
94 self.assertFalse(self.__check_path('deteteme'))
94
95
95 sg1 = _make_group('deleteme', parent_id=self.g1.group_id)
96 sg1 = _make_group('deleteme', parent_id=self.g1.group_id)
96 self.__delete_group(sg1.group_id)
97 self.__delete_group(sg1.group_id)
97
98
98 self.assertEqual(RepoGroup.get(sg1.group_id), None)
99 self.assertEqual(RepoGroup.get(sg1.group_id), None)
99 self.assertFalse(self.__check_path('test1', 'deteteme'))
100 self.assertFalse(self.__check_path('test1', 'deteteme'))
100
101
101 def test_rename_single_group(self):
102 def test_rename_single_group(self):
102 sg1 = _make_group('initial')
103 sg1 = _make_group('initial')
103
104
104 new_sg1 = self.__update_group(sg1.group_id, 'after')
105 new_sg1 = self.__update_group(sg1.group_id, 'after')
105 self.assertTrue(self.__check_path('after'))
106 self.assertTrue(self.__check_path('after'))
106 self.assertEqual(RepoGroup.get_by_group_name('initial'), None)
107 self.assertEqual(RepoGroup.get_by_group_name('initial'), None)
107
108
108 def test_update_group_parent(self):
109 def test_update_group_parent(self):
109
110
110 sg1 = _make_group('initial', parent_id=self.g1.group_id)
111 sg1 = _make_group('initial', parent_id=self.g1.group_id)
111
112
112 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id)
113 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id)
113 self.assertTrue(self.__check_path('test1', 'after'))
114 self.assertTrue(self.__check_path('test1', 'after'))
114 self.assertEqual(RepoGroup.get_by_group_name('test1/initial'), None)
115 self.assertEqual(RepoGroup.get_by_group_name('test1/initial'), None)
115
116
116 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id)
117 new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id)
117 self.assertTrue(self.__check_path('test3', 'after'))
118 self.assertTrue(self.__check_path('test3', 'after'))
118 self.assertEqual(RepoGroup.get_by_group_name('test3/initial'), None)
119 self.assertEqual(RepoGroup.get_by_group_name('test3/initial'), None)
119
120
120 new_sg1 = self.__update_group(sg1.group_id, 'hello')
121 new_sg1 = self.__update_group(sg1.group_id, 'hello')
121 self.assertTrue(self.__check_path('hello'))
122 self.assertTrue(self.__check_path('hello'))
122
123
123 self.assertEqual(RepoGroup.get_by_group_name('hello'), new_sg1)
124 self.assertEqual(RepoGroup.get_by_group_name('hello'), new_sg1)
124
125
125 def test_subgrouping_with_repo(self):
126 def test_subgrouping_with_repo(self):
126
127
127 g1 = _make_group('g1')
128 g1 = _make_group('g1')
128 g2 = _make_group('g2')
129 g2 = _make_group('g2')
129
130
130 # create new repo
131 # create new repo
131 form_data = dict(repo_name='john',
132 form_data = dict(repo_name='john',
132 repo_name_full='john',
133 repo_name_full='john',
133 fork_name=None,
134 fork_name=None,
134 description=None,
135 description=None,
135 repo_group=None,
136 repo_group=None,
136 private=False,
137 private=False,
137 repo_type='hg',
138 repo_type='hg',
138 clone_uri=None)
139 clone_uri=None)
139 cur_user = User.get_by_username(TEST_USER_ADMIN_LOGIN)
140 cur_user = User.get_by_username(TEST_USER_ADMIN_LOGIN)
140 r = RepoModel().create(form_data, cur_user)
141 r = RepoModel().create(form_data, cur_user)
141
142
142 self.assertEqual(r.repo_name, 'john')
143 self.assertEqual(r.repo_name, 'john')
143
144
144 # put repo into group
145 # put repo into group
145 form_data = form_data
146 form_data = form_data
146 form_data['repo_group'] = g1.group_id
147 form_data['repo_group'] = g1.group_id
147 form_data['perms_new'] = []
148 form_data['perms_new'] = []
148 form_data['perms_updates'] = []
149 form_data['perms_updates'] = []
149 RepoModel().update(r.repo_name, form_data)
150 RepoModel().update(r.repo_name, form_data)
150 self.assertEqual(r.repo_name, 'g1/john')
151 self.assertEqual(r.repo_name, 'g1/john')
151
152
152 self.__update_group(g1.group_id, 'g1', parent_id=g2.group_id)
153 self.__update_group(g1.group_id, 'g1', parent_id=g2.group_id)
153 self.assertTrue(self.__check_path('g2', 'g1'))
154 self.assertTrue(self.__check_path('g2', 'g1'))
154
155
155 # test repo
156 # test repo
156 self.assertEqual(r.repo_name, os.path.join('g2', 'g1', r.just_name))
157 self.assertEqual(r.repo_name, RepoGroup.url_sep().join(['g2', 'g1', r.just_name]))
157
158
158
159 def test_move_to_root(self):
159 def test_move_to_root(self):
160 g1 = _make_group('t11')
160 g1 = _make_group('t11')
161 Session.commit()
161 Session.commit()
162 g2 = _make_group('t22',parent_id=g1.group_id)
162 g2 = _make_group('t22', parent_id=g1.group_id)
163 Session.commit()
163 Session.commit()
164
164
165 self.assertEqual(g2.full_path,'t11/t22')
165 self.assertEqual(g2.full_path, 't11/t22')
166 self.assertTrue(self.__check_path('t11', 't22'))
166 self.assertTrue(self.__check_path('t11', 't22'))
167
167
168 g2 = self.__update_group(g2.group_id, 'g22', parent_id=None)
168 g2 = self.__update_group(g2.group_id, 'g22', parent_id=None)
169 Session.commit()
169 Session.commit()
170
170
171 self.assertEqual(g2.group_name,'g22')
171 self.assertEqual(g2.group_name, 'g22')
172 # we moved out group from t1 to '' so it's full path should be 'g2'
172 # we moved out group from t1 to '' so it's full path should be 'g2'
173 self.assertEqual(g2.full_path,'g22')
173 self.assertEqual(g2.full_path, 'g22')
174 self.assertFalse(self.__check_path('t11', 't22'))
174 self.assertFalse(self.__check_path('t11', 't22'))
175 self.assertTrue(self.__check_path('g22'))
175 self.assertTrue(self.__check_path('g22'))
176
176
177
177
178 class TestUser(unittest.TestCase):
178 class TestUser(unittest.TestCase):
179 def __init__(self, methodName='runTest'):
179 def __init__(self, methodName='runTest'):
180 Session.remove()
180 Session.remove()
181 super(TestUser, self).__init__(methodName=methodName)
181 super(TestUser, self).__init__(methodName=methodName)
182
182
183 def test_create_and_remove(self):
183 def test_create_and_remove(self):
184 usr = UserModel().create_or_update(username=u'test_user', password=u'qweqwe',
184 usr = UserModel().create_or_update(username=u'test_user', password=u'qweqwe',
185 email=u'u232@rhodecode.org',
185 email=u'u232@rhodecode.org',
186 name=u'u1', lastname=u'u1')
186 name=u'u1', lastname=u'u1')
187 Session.commit()
187 Session.commit()
188 self.assertEqual(User.get_by_username(u'test_user'), usr)
188 self.assertEqual(User.get_by_username(u'test_user'), usr)
189
189
190 # make users group
190 # make users group
191 users_group = UsersGroupModel().create('some_example_group')
191 users_group = UsersGroupModel().create('some_example_group')
192 Session.commit()
192 Session.commit()
193
193
194 UsersGroupModel().add_user_to_group(users_group, usr)
194 UsersGroupModel().add_user_to_group(users_group, usr)
195 Session.commit()
195 Session.commit()
196
196
197 self.assertEqual(UsersGroup.get(users_group.users_group_id), users_group)
197 self.assertEqual(UsersGroup.get(users_group.users_group_id), users_group)
198 self.assertEqual(UsersGroupMember.query().count(), 1)
198 self.assertEqual(UsersGroupMember.query().count(), 1)
199 UserModel().delete(usr.user_id)
199 UserModel().delete(usr.user_id)
200 Session.commit()
200 Session.commit()
201
201
202 self.assertEqual(UsersGroupMember.query().all(), [])
202 self.assertEqual(UsersGroupMember.query().all(), [])
203
203
204
204
205 class TestNotifications(unittest.TestCase):
205 class TestNotifications(unittest.TestCase):
206
206
207 def __init__(self, methodName='runTest'):
207 def __init__(self, methodName='runTest'):
208 Session.remove()
208 Session.remove()
209 self.u1 = UserModel().create_or_update(username=u'u1',
209 self.u1 = UserModel().create_or_update(username=u'u1',
210 password=u'qweqwe',
210 password=u'qweqwe',
211 email=u'u1@rhodecode.org',
211 email=u'u1@rhodecode.org',
212 name=u'u1', lastname=u'u1')
212 name=u'u1', lastname=u'u1')
213 Session.commit()
213 Session.commit()
214 self.u1 = self.u1.user_id
214 self.u1 = self.u1.user_id
215
215
216 self.u2 = UserModel().create_or_update(username=u'u2',
216 self.u2 = UserModel().create_or_update(username=u'u2',
217 password=u'qweqwe',
217 password=u'qweqwe',
218 email=u'u2@rhodecode.org',
218 email=u'u2@rhodecode.org',
219 name=u'u2', lastname=u'u3')
219 name=u'u2', lastname=u'u3')
220 Session.commit()
220 Session.commit()
221 self.u2 = self.u2.user_id
221 self.u2 = self.u2.user_id
222
222
223 self.u3 = UserModel().create_or_update(username=u'u3',
223 self.u3 = UserModel().create_or_update(username=u'u3',
224 password=u'qweqwe',
224 password=u'qweqwe',
225 email=u'u3@rhodecode.org',
225 email=u'u3@rhodecode.org',
226 name=u'u3', lastname=u'u3')
226 name=u'u3', lastname=u'u3')
227 Session.commit()
227 Session.commit()
228 self.u3 = self.u3.user_id
228 self.u3 = self.u3.user_id
229
229
230 super(TestNotifications, self).__init__(methodName=methodName)
230 super(TestNotifications, self).__init__(methodName=methodName)
231
231
232 def _clean_notifications(self):
232 def _clean_notifications(self):
233 for n in Notification.query().all():
233 for n in Notification.query().all():
234 Session.delete(n)
234 Session.delete(n)
235
235
236 Session.commit()
236 Session.commit()
237 self.assertEqual(Notification.query().all(), [])
237 self.assertEqual(Notification.query().all(), [])
238
238
239 def tearDown(self):
239 def tearDown(self):
240 self._clean_notifications()
240 self._clean_notifications()
241
241
242 def test_create_notification(self):
242 def test_create_notification(self):
243 self.assertEqual([], Notification.query().all())
243 self.assertEqual([], Notification.query().all())
244 self.assertEqual([], UserNotification.query().all())
244 self.assertEqual([], UserNotification.query().all())
245
245
246 usrs = [self.u1, self.u2]
246 usrs = [self.u1, self.u2]
247 notification = NotificationModel().create(created_by=self.u1,
247 notification = NotificationModel().create(created_by=self.u1,
248 subject=u'subj', body=u'hi there',
248 subject=u'subj', body=u'hi there',
249 recipients=usrs)
249 recipients=usrs)
250 Session.commit()
250 Session.commit()
251 u1 = User.get(self.u1)
251 u1 = User.get(self.u1)
252 u2 = User.get(self.u2)
252 u2 = User.get(self.u2)
253 u3 = User.get(self.u3)
253 u3 = User.get(self.u3)
254 notifications = Notification.query().all()
254 notifications = Notification.query().all()
255 self.assertEqual(len(notifications), 1)
255 self.assertEqual(len(notifications), 1)
256
256
257 unotification = UserNotification.query()\
257 unotification = UserNotification.query()\
258 .filter(UserNotification.notification == notification).all()
258 .filter(UserNotification.notification == notification).all()
259
259
260 self.assertEqual(notifications[0].recipients, [u1, u2])
260 self.assertEqual(notifications[0].recipients, [u1, u2])
261 self.assertEqual(notification.notification_id,
261 self.assertEqual(notification.notification_id,
262 notifications[0].notification_id)
262 notifications[0].notification_id)
263 self.assertEqual(len(unotification), len(usrs))
263 self.assertEqual(len(unotification), len(usrs))
264 self.assertEqual([x.user.user_id for x in unotification], usrs)
264 self.assertEqual([x.user.user_id for x in unotification], usrs)
265
265
266 def test_user_notifications(self):
266 def test_user_notifications(self):
267 self.assertEqual([], Notification.query().all())
267 self.assertEqual([], Notification.query().all())
268 self.assertEqual([], UserNotification.query().all())
268 self.assertEqual([], UserNotification.query().all())
269
269
270 notification1 = NotificationModel().create(created_by=self.u1,
270 notification1 = NotificationModel().create(created_by=self.u1,
271 subject=u'subj', body=u'hi there1',
271 subject=u'subj', body=u'hi there1',
272 recipients=[self.u3])
272 recipients=[self.u3])
273 Session.commit()
273 Session.commit()
274 notification2 = NotificationModel().create(created_by=self.u1,
274 notification2 = NotificationModel().create(created_by=self.u1,
275 subject=u'subj', body=u'hi there2',
275 subject=u'subj', body=u'hi there2',
276 recipients=[self.u3])
276 recipients=[self.u3])
277 Session.commit()
277 Session.commit()
278 u3 = Session.query(User).get(self.u3)
278 u3 = Session.query(User).get(self.u3)
279
279
280 self.assertEqual(sorted([x.notification for x in u3.notifications]),
280 self.assertEqual(sorted([x.notification for x in u3.notifications]),
281 sorted([notification2, notification1]))
281 sorted([notification2, notification1]))
282
282
283 def test_delete_notifications(self):
283 def test_delete_notifications(self):
284 self.assertEqual([], Notification.query().all())
284 self.assertEqual([], Notification.query().all())
285 self.assertEqual([], UserNotification.query().all())
285 self.assertEqual([], UserNotification.query().all())
286
286
287 notification = NotificationModel().create(created_by=self.u1,
287 notification = NotificationModel().create(created_by=self.u1,
288 subject=u'title', body=u'hi there3',
288 subject=u'title', body=u'hi there3',
289 recipients=[self.u3, self.u1, self.u2])
289 recipients=[self.u3, self.u1, self.u2])
290 Session.commit()
290 Session.commit()
291 notifications = Notification.query().all()
291 notifications = Notification.query().all()
292 self.assertTrue(notification in notifications)
292 self.assertTrue(notification in notifications)
293
293
294 Notification.delete(notification.notification_id)
294 Notification.delete(notification.notification_id)
295 Session.commit()
295 Session.commit()
296
296
297 notifications = Notification.query().all()
297 notifications = Notification.query().all()
298 self.assertFalse(notification in notifications)
298 self.assertFalse(notification in notifications)
299
299
300 un = UserNotification.query().filter(UserNotification.notification
300 un = UserNotification.query().filter(UserNotification.notification
301 == notification).all()
301 == notification).all()
302 self.assertEqual(un, [])
302 self.assertEqual(un, [])
303
303
304 def test_delete_association(self):
304 def test_delete_association(self):
305
305
306 self.assertEqual([], Notification.query().all())
306 self.assertEqual([], Notification.query().all())
307 self.assertEqual([], UserNotification.query().all())
307 self.assertEqual([], UserNotification.query().all())
308
308
309 notification = NotificationModel().create(created_by=self.u1,
309 notification = NotificationModel().create(created_by=self.u1,
310 subject=u'title', body=u'hi there3',
310 subject=u'title', body=u'hi there3',
311 recipients=[self.u3, self.u1, self.u2])
311 recipients=[self.u3, self.u1, self.u2])
312 Session.commit()
312 Session.commit()
313
313
314 unotification = UserNotification.query()\
314 unotification = UserNotification.query()\
315 .filter(UserNotification.notification ==
315 .filter(UserNotification.notification ==
316 notification)\
316 notification)\
317 .filter(UserNotification.user_id == self.u3)\
317 .filter(UserNotification.user_id == self.u3)\
318 .scalar()
318 .scalar()
319
319
320 self.assertEqual(unotification.user_id, self.u3)
320 self.assertEqual(unotification.user_id, self.u3)
321
321
322 NotificationModel().delete(self.u3,
322 NotificationModel().delete(self.u3,
323 notification.notification_id)
323 notification.notification_id)
324 Session.commit()
324 Session.commit()
325
325
326 u3notification = UserNotification.query()\
326 u3notification = UserNotification.query()\
327 .filter(UserNotification.notification ==
327 .filter(UserNotification.notification ==
328 notification)\
328 notification)\
329 .filter(UserNotification.user_id == self.u3)\
329 .filter(UserNotification.user_id == self.u3)\
330 .scalar()
330 .scalar()
331
331
332 self.assertEqual(u3notification, None)
332 self.assertEqual(u3notification, None)
333
333
334 # notification object is still there
334 # notification object is still there
335 self.assertEqual(Notification.query().all(), [notification])
335 self.assertEqual(Notification.query().all(), [notification])
336
336
337 #u1 and u2 still have assignments
337 #u1 and u2 still have assignments
338 u1notification = UserNotification.query()\
338 u1notification = UserNotification.query()\
339 .filter(UserNotification.notification ==
339 .filter(UserNotification.notification ==
340 notification)\
340 notification)\
341 .filter(UserNotification.user_id == self.u1)\
341 .filter(UserNotification.user_id == self.u1)\
342 .scalar()
342 .scalar()
343 self.assertNotEqual(u1notification, None)
343 self.assertNotEqual(u1notification, None)
344 u2notification = UserNotification.query()\
344 u2notification = UserNotification.query()\
345 .filter(UserNotification.notification ==
345 .filter(UserNotification.notification ==
346 notification)\
346 notification)\
347 .filter(UserNotification.user_id == self.u2)\
347 .filter(UserNotification.user_id == self.u2)\
348 .scalar()
348 .scalar()
349 self.assertNotEqual(u2notification, None)
349 self.assertNotEqual(u2notification, None)
350
350
351 def test_notification_counter(self):
351 def test_notification_counter(self):
352 self._clean_notifications()
352 self._clean_notifications()
353 self.assertEqual([], Notification.query().all())
353 self.assertEqual([], Notification.query().all())
354 self.assertEqual([], UserNotification.query().all())
354 self.assertEqual([], UserNotification.query().all())
355
355
356 NotificationModel().create(created_by=self.u1,
356 NotificationModel().create(created_by=self.u1,
357 subject=u'title', body=u'hi there_delete',
357 subject=u'title', body=u'hi there_delete',
358 recipients=[self.u3, self.u1])
358 recipients=[self.u3, self.u1])
359 Session.commit()
359 Session.commit()
360
360
361 self.assertEqual(NotificationModel()
361 self.assertEqual(NotificationModel()
362 .get_unread_cnt_for_user(self.u1), 1)
362 .get_unread_cnt_for_user(self.u1), 1)
363 self.assertEqual(NotificationModel()
363 self.assertEqual(NotificationModel()
364 .get_unread_cnt_for_user(self.u2), 0)
364 .get_unread_cnt_for_user(self.u2), 0)
365 self.assertEqual(NotificationModel()
365 self.assertEqual(NotificationModel()
366 .get_unread_cnt_for_user(self.u3), 1)
366 .get_unread_cnt_for_user(self.u3), 1)
367
367
368 notification = NotificationModel().create(created_by=self.u1,
368 notification = NotificationModel().create(created_by=self.u1,
369 subject=u'title', body=u'hi there3',
369 subject=u'title', body=u'hi there3',
370 recipients=[self.u3, self.u1, self.u2])
370 recipients=[self.u3, self.u1, self.u2])
371 Session.commit()
371 Session.commit()
372
372
373 self.assertEqual(NotificationModel()
373 self.assertEqual(NotificationModel()
374 .get_unread_cnt_for_user(self.u1), 2)
374 .get_unread_cnt_for_user(self.u1), 2)
375 self.assertEqual(NotificationModel()
375 self.assertEqual(NotificationModel()
376 .get_unread_cnt_for_user(self.u2), 1)
376 .get_unread_cnt_for_user(self.u2), 1)
377 self.assertEqual(NotificationModel()
377 self.assertEqual(NotificationModel()
378 .get_unread_cnt_for_user(self.u3), 2)
378 .get_unread_cnt_for_user(self.u3), 2)
379
379
380
380
381 class TestUsers(unittest.TestCase):
381 class TestUsers(unittest.TestCase):
382
382
383 def __init__(self, methodName='runTest'):
383 def __init__(self, methodName='runTest'):
384 super(TestUsers, self).__init__(methodName=methodName)
384 super(TestUsers, self).__init__(methodName=methodName)
385
385
386 def setUp(self):
386 def setUp(self):
387 self.u1 = UserModel().create_or_update(username=u'u1',
387 self.u1 = UserModel().create_or_update(username=u'u1',
388 password=u'qweqwe',
388 password=u'qweqwe',
389 email=u'u1@rhodecode.org',
389 email=u'u1@rhodecode.org',
390 name=u'u1', lastname=u'u1')
390 name=u'u1', lastname=u'u1')
391
391
392 def tearDown(self):
392 def tearDown(self):
393 perm = Permission.query().all()
393 perm = Permission.query().all()
394 for p in perm:
394 for p in perm:
395 UserModel().revoke_perm(self.u1, p)
395 UserModel().revoke_perm(self.u1, p)
396
396
397 UserModel().delete(self.u1)
397 UserModel().delete(self.u1)
398 Session.commit()
398 Session.commit()
399
399
400 def test_add_perm(self):
400 def test_add_perm(self):
401 perm = Permission.query().all()[0]
401 perm = Permission.query().all()[0]
402 UserModel().grant_perm(self.u1, perm)
402 UserModel().grant_perm(self.u1, perm)
403 Session.commit()
403 Session.commit()
404 self.assertEqual(UserModel().has_perm(self.u1, perm), True)
404 self.assertEqual(UserModel().has_perm(self.u1, perm), True)
405
405
406 def test_has_perm(self):
406 def test_has_perm(self):
407 perm = Permission.query().all()
407 perm = Permission.query().all()
408 for p in perm:
408 for p in perm:
409 has_p = UserModel().has_perm(self.u1, p)
409 has_p = UserModel().has_perm(self.u1, p)
410 self.assertEqual(False, has_p)
410 self.assertEqual(False, has_p)
411
411
412 def test_revoke_perm(self):
412 def test_revoke_perm(self):
413 perm = Permission.query().all()[0]
413 perm = Permission.query().all()[0]
414 UserModel().grant_perm(self.u1, perm)
414 UserModel().grant_perm(self.u1, perm)
415 Session.commit()
415 Session.commit()
416 self.assertEqual(UserModel().has_perm(self.u1, perm), True)
416 self.assertEqual(UserModel().has_perm(self.u1, perm), True)
417
417
418 #revoke
418 #revoke
419 UserModel().revoke_perm(self.u1, perm)
419 UserModel().revoke_perm(self.u1, perm)
420 Session.commit()
420 Session.commit()
421 self.assertEqual(UserModel().has_perm(self.u1, perm), False)
421 self.assertEqual(UserModel().has_perm(self.u1, perm), False)
422
422
423
423
424 class TestPermissions(unittest.TestCase):
424 class TestPermissions(unittest.TestCase):
425 def __init__(self, methodName='runTest'):
425 def __init__(self, methodName='runTest'):
426 super(TestPermissions, self).__init__(methodName=methodName)
426 super(TestPermissions, self).__init__(methodName=methodName)
427
427
428 def setUp(self):
428 def setUp(self):
429 self.u1 = UserModel().create_or_update(
429 self.u1 = UserModel().create_or_update(
430 username=u'u1', password=u'qweqwe',
430 username=u'u1', password=u'qweqwe',
431 email=u'u1@rhodecode.org', name=u'u1', lastname=u'u1'
431 email=u'u1@rhodecode.org', name=u'u1', lastname=u'u1'
432 )
432 )
433 self.u2 = UserModel().create_or_update(
433 self.u2 = UserModel().create_or_update(
434 username=u'u2', password=u'qweqwe',
434 username=u'u2', password=u'qweqwe',
435 email=u'u2@rhodecode.org', name=u'u2', lastname=u'u2'
435 email=u'u2@rhodecode.org', name=u'u2', lastname=u'u2'
436 )
436 )
437 self.anon = User.get_by_username('default')
437 self.anon = User.get_by_username('default')
438 self.a1 = UserModel().create_or_update(
438 self.a1 = UserModel().create_or_update(
439 username=u'a1', password=u'qweqwe',
439 username=u'a1', password=u'qweqwe',
440 email=u'a1@rhodecode.org', name=u'a1', lastname=u'a1', admin=True
440 email=u'a1@rhodecode.org', name=u'a1', lastname=u'a1', admin=True
441 )
441 )
442 Session.commit()
442 Session.commit()
443
443
444 def tearDown(self):
444 def tearDown(self):
445 if hasattr(self, 'test_repo'):
445 if hasattr(self, 'test_repo'):
446 RepoModel().delete(repo=self.test_repo)
446 RepoModel().delete(repo=self.test_repo)
447 UserModel().delete(self.u1)
447 UserModel().delete(self.u1)
448 UserModel().delete(self.u2)
448 UserModel().delete(self.u2)
449 UserModel().delete(self.a1)
449 UserModel().delete(self.a1)
450 if hasattr(self, 'g1'):
450 if hasattr(self, 'g1'):
451 ReposGroupModel().delete(self.g1.group_id)
451 ReposGroupModel().delete(self.g1.group_id)
452 if hasattr(self, 'g2'):
452 if hasattr(self, 'g2'):
453 ReposGroupModel().delete(self.g2.group_id)
453 ReposGroupModel().delete(self.g2.group_id)
454
454
455 if hasattr(self, 'ug1'):
455 if hasattr(self, 'ug1'):
456 UsersGroupModel().delete(self.ug1, force=True)
456 UsersGroupModel().delete(self.ug1, force=True)
457
457
458 Session.commit()
458 Session.commit()
459
459
460 def test_default_perms_set(self):
460 def test_default_perms_set(self):
461 u1_auth = AuthUser(user_id=self.u1.user_id)
461 u1_auth = AuthUser(user_id=self.u1.user_id)
462 perms = {
462 perms = {
463 'repositories_groups': {},
463 'repositories_groups': {},
464 'global': set([u'hg.create.repository', u'repository.read',
464 'global': set([u'hg.create.repository', u'repository.read',
465 u'hg.register.manual_activate']),
465 u'hg.register.manual_activate']),
466 'repositories': {u'vcs_test_hg': u'repository.read'}
466 'repositories': {u'vcs_test_hg': u'repository.read'}
467 }
467 }
468 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
468 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
469 perms['repositories'][HG_REPO])
469 perms['repositories'][HG_REPO])
470 new_perm = 'repository.write'
470 new_perm = 'repository.write'
471 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
471 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
472 Session.commit()
472 Session.commit()
473
473
474 u1_auth = AuthUser(user_id=self.u1.user_id)
474 u1_auth = AuthUser(user_id=self.u1.user_id)
475 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm)
475 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm)
476
476
477 def test_default_admin_perms_set(self):
477 def test_default_admin_perms_set(self):
478 a1_auth = AuthUser(user_id=self.a1.user_id)
478 a1_auth = AuthUser(user_id=self.a1.user_id)
479 perms = {
479 perms = {
480 'repositories_groups': {},
480 'repositories_groups': {},
481 'global': set([u'hg.admin']),
481 'global': set([u'hg.admin']),
482 'repositories': {u'vcs_test_hg': u'repository.admin'}
482 'repositories': {u'vcs_test_hg': u'repository.admin'}
483 }
483 }
484 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
484 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
485 perms['repositories'][HG_REPO])
485 perms['repositories'][HG_REPO])
486 new_perm = 'repository.write'
486 new_perm = 'repository.write'
487 RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1, perm=new_perm)
487 RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1, perm=new_perm)
488 Session.commit()
488 Session.commit()
489 # cannot really downgrade admins permissions !? they still get's set as
489 # cannot really downgrade admins permissions !? they still get's set as
490 # admin !
490 # admin !
491 u1_auth = AuthUser(user_id=self.a1.user_id)
491 u1_auth = AuthUser(user_id=self.a1.user_id)
492 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
492 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
493 perms['repositories'][HG_REPO])
493 perms['repositories'][HG_REPO])
494
494
495 def test_default_group_perms(self):
495 def test_default_group_perms(self):
496 self.g1 = _make_group('test1', skip_if_exists=True)
496 self.g1 = _make_group('test1', skip_if_exists=True)
497 self.g2 = _make_group('test2', skip_if_exists=True)
497 self.g2 = _make_group('test2', skip_if_exists=True)
498 u1_auth = AuthUser(user_id=self.u1.user_id)
498 u1_auth = AuthUser(user_id=self.u1.user_id)
499 perms = {
499 perms = {
500 'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
500 'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
501 'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']),
501 'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']),
502 'repositories': {u'vcs_test_hg': u'repository.read'}
502 'repositories': {u'vcs_test_hg': u'repository.read'}
503 }
503 }
504 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
504 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
505 perms['repositories'][HG_REPO])
505 perms['repositories'][HG_REPO])
506 self.assertEqual(u1_auth.permissions['repositories_groups'],
506 self.assertEqual(u1_auth.permissions['repositories_groups'],
507 perms['repositories_groups'])
507 perms['repositories_groups'])
508
508
509 def test_default_admin_group_perms(self):
509 def test_default_admin_group_perms(self):
510 self.g1 = _make_group('test1', skip_if_exists=True)
510 self.g1 = _make_group('test1', skip_if_exists=True)
511 self.g2 = _make_group('test2', skip_if_exists=True)
511 self.g2 = _make_group('test2', skip_if_exists=True)
512 a1_auth = AuthUser(user_id=self.a1.user_id)
512 a1_auth = AuthUser(user_id=self.a1.user_id)
513 perms = {
513 perms = {
514 'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
514 'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
515 'global': set(['hg.admin']),
515 'global': set(['hg.admin']),
516 'repositories': {u'vcs_test_hg': 'repository.admin'}
516 'repositories': {u'vcs_test_hg': 'repository.admin'}
517 }
517 }
518
518
519 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
519 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
520 perms['repositories'][HG_REPO])
520 perms['repositories'][HG_REPO])
521 self.assertEqual(a1_auth.permissions['repositories_groups'],
521 self.assertEqual(a1_auth.permissions['repositories_groups'],
522 perms['repositories_groups'])
522 perms['repositories_groups'])
523
523
524 def test_propagated_permission_from_users_group(self):
524 def test_propagated_permission_from_users_group(self):
525 # make group
525 # make group
526 self.ug1 = UsersGroupModel().create('G1')
526 self.ug1 = UsersGroupModel().create('G1')
527 # add user to group
527 # add user to group
528 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
528 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
529
529
530 # set permission to lower
530 # set permission to lower
531 new_perm = 'repository.none'
531 new_perm = 'repository.none'
532 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
532 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
533 Session.commit()
533 Session.commit()
534 u1_auth = AuthUser(user_id=self.u1.user_id)
534 u1_auth = AuthUser(user_id=self.u1.user_id)
535 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
535 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
536 new_perm)
536 new_perm)
537
537
538 # grant perm for group this should override permission from user
538 # grant perm for group this should override permission from user
539 new_perm = 'repository.write'
539 new_perm = 'repository.write'
540 RepoModel().grant_users_group_permission(repo=HG_REPO,
540 RepoModel().grant_users_group_permission(repo=HG_REPO,
541 group_name=self.ug1,
541 group_name=self.ug1,
542 perm=new_perm)
542 perm=new_perm)
543 # check perms
543 # check perms
544 u1_auth = AuthUser(user_id=self.u1.user_id)
544 u1_auth = AuthUser(user_id=self.u1.user_id)
545 perms = {
545 perms = {
546 'repositories_groups': {},
546 'repositories_groups': {},
547 'global': set([u'hg.create.repository', u'repository.read',
547 'global': set([u'hg.create.repository', u'repository.read',
548 u'hg.register.manual_activate']),
548 u'hg.register.manual_activate']),
549 'repositories': {u'vcs_test_hg': u'repository.read'}
549 'repositories': {u'vcs_test_hg': u'repository.read'}
550 }
550 }
551 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
551 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
552 new_perm)
552 new_perm)
553 self.assertEqual(u1_auth.permissions['repositories_groups'],
553 self.assertEqual(u1_auth.permissions['repositories_groups'],
554 perms['repositories_groups'])
554 perms['repositories_groups'])
555
555
556 def test_propagated_permission_from_users_group_lower_weight(self):
556 def test_propagated_permission_from_users_group_lower_weight(self):
557 # make group
557 # make group
558 self.ug1 = UsersGroupModel().create('G1')
558 self.ug1 = UsersGroupModel().create('G1')
559 # add user to group
559 # add user to group
560 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
560 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
561
561
562 # set permission to lower
562 # set permission to lower
563 new_perm_h = 'repository.write'
563 new_perm_h = 'repository.write'
564 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
564 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
565 perm=new_perm_h)
565 perm=new_perm_h)
566 Session.commit()
566 Session.commit()
567 u1_auth = AuthUser(user_id=self.u1.user_id)
567 u1_auth = AuthUser(user_id=self.u1.user_id)
568 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
568 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
569 new_perm_h)
569 new_perm_h)
570
570
571 # grant perm for group this should NOT override permission from user
571 # grant perm for group this should NOT override permission from user
572 # since it's lower than granted
572 # since it's lower than granted
573 new_perm_l = 'repository.read'
573 new_perm_l = 'repository.read'
574 RepoModel().grant_users_group_permission(repo=HG_REPO,
574 RepoModel().grant_users_group_permission(repo=HG_REPO,
575 group_name=self.ug1,
575 group_name=self.ug1,
576 perm=new_perm_l)
576 perm=new_perm_l)
577 # check perms
577 # check perms
578 u1_auth = AuthUser(user_id=self.u1.user_id)
578 u1_auth = AuthUser(user_id=self.u1.user_id)
579 perms = {
579 perms = {
580 'repositories_groups': {},
580 'repositories_groups': {},
581 'global': set([u'hg.create.repository', u'repository.read',
581 'global': set([u'hg.create.repository', u'repository.read',
582 u'hg.register.manual_activate']),
582 u'hg.register.manual_activate']),
583 'repositories': {u'vcs_test_hg': u'repository.write'}
583 'repositories': {u'vcs_test_hg': u'repository.write'}
584 }
584 }
585 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
585 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
586 new_perm_h)
586 new_perm_h)
587 self.assertEqual(u1_auth.permissions['repositories_groups'],
587 self.assertEqual(u1_auth.permissions['repositories_groups'],
588 perms['repositories_groups'])
588 perms['repositories_groups'])
589
589
590 def test_repo_in_group_permissions(self):
590 def test_repo_in_group_permissions(self):
591 self.g1 = _make_group('group1', skip_if_exists=True)
591 self.g1 = _make_group('group1', skip_if_exists=True)
592 self.g2 = _make_group('group2', skip_if_exists=True)
592 self.g2 = _make_group('group2', skip_if_exists=True)
593 Session.commit()
593 Session.commit()
594 # both perms should be read !
594 # both perms should be read !
595 u1_auth = AuthUser(user_id=self.u1.user_id)
595 u1_auth = AuthUser(user_id=self.u1.user_id)
596 self.assertEqual(u1_auth.permissions['repositories_groups'],
596 self.assertEqual(u1_auth.permissions['repositories_groups'],
597 {u'group1': u'group.read', u'group2': u'group.read'})
597 {u'group1': u'group.read', u'group2': u'group.read'})
598
598
599 a1_auth = AuthUser(user_id=self.anon.user_id)
599 a1_auth = AuthUser(user_id=self.anon.user_id)
600 self.assertEqual(a1_auth.permissions['repositories_groups'],
600 self.assertEqual(a1_auth.permissions['repositories_groups'],
601 {u'group1': u'group.read', u'group2': u'group.read'})
601 {u'group1': u'group.read', u'group2': u'group.read'})
602
602
603 #Change perms to none for both groups
603 #Change perms to none for both groups
604 ReposGroupModel().grant_user_permission(repos_group=self.g1,
604 ReposGroupModel().grant_user_permission(repos_group=self.g1,
605 user=self.anon,
605 user=self.anon,
606 perm='group.none')
606 perm='group.none')
607 ReposGroupModel().grant_user_permission(repos_group=self.g2,
607 ReposGroupModel().grant_user_permission(repos_group=self.g2,
608 user=self.anon,
608 user=self.anon,
609 perm='group.none')
609 perm='group.none')
610
610
611
611
612 u1_auth = AuthUser(user_id=self.u1.user_id)
612 u1_auth = AuthUser(user_id=self.u1.user_id)
613 self.assertEqual(u1_auth.permissions['repositories_groups'],
613 self.assertEqual(u1_auth.permissions['repositories_groups'],
614 {u'group1': u'group.none', u'group2': u'group.none'})
614 {u'group1': u'group.none', u'group2': u'group.none'})
615
615
616 a1_auth = AuthUser(user_id=self.anon.user_id)
616 a1_auth = AuthUser(user_id=self.anon.user_id)
617 self.assertEqual(a1_auth.permissions['repositories_groups'],
617 self.assertEqual(a1_auth.permissions['repositories_groups'],
618 {u'group1': u'group.none', u'group2': u'group.none'})
618 {u'group1': u'group.none', u'group2': u'group.none'})
619
619
620 # add repo to group
620 # add repo to group
621 form_data = {
621 form_data = {
622 'repo_name':HG_REPO,
622 'repo_name':HG_REPO,
623 'repo_name_full':os.path.join(self.g1.group_name,HG_REPO),
623 'repo_name_full':RepoGroup.url_sep().join([self.g1.group_name,HG_REPO]),
624 'repo_type':'hg',
624 'repo_type':'hg',
625 'clone_uri':'',
625 'clone_uri':'',
626 'repo_group':self.g1.group_id,
626 'repo_group':self.g1.group_id,
627 'description':'desc',
627 'description':'desc',
628 'private':False
628 'private':False
629 }
629 }
630 self.test_repo = RepoModel().create(form_data, cur_user=self.u1)
630 self.test_repo = RepoModel().create(form_data, cur_user=self.u1)
631 Session.commit()
631 Session.commit()
632
632
633 u1_auth = AuthUser(user_id=self.u1.user_id)
633 u1_auth = AuthUser(user_id=self.u1.user_id)
634 self.assertEqual(u1_auth.permissions['repositories_groups'],
634 self.assertEqual(u1_auth.permissions['repositories_groups'],
635 {u'group1': u'group.none', u'group2': u'group.none'})
635 {u'group1': u'group.none', u'group2': u'group.none'})
636
636
637 a1_auth = AuthUser(user_id=self.anon.user_id)
637 a1_auth = AuthUser(user_id=self.anon.user_id)
638 self.assertEqual(a1_auth.permissions['repositories_groups'],
638 self.assertEqual(a1_auth.permissions['repositories_groups'],
639 {u'group1': u'group.none', u'group2': u'group.none'})
639 {u'group1': u'group.none', u'group2': u'group.none'})
640
640
641 #grant permission for u2 !
641 #grant permission for u2 !
642 ReposGroupModel().grant_user_permission(repos_group=self.g1,
642 ReposGroupModel().grant_user_permission(repos_group=self.g1,
643 user=self.u2,
643 user=self.u2,
644 perm='group.read')
644 perm='group.read')
645 ReposGroupModel().grant_user_permission(repos_group=self.g2,
645 ReposGroupModel().grant_user_permission(repos_group=self.g2,
646 user=self.u2,
646 user=self.u2,
647 perm='group.read')
647 perm='group.read')
648 Session.commit()
648 Session.commit()
649 self.assertNotEqual(self.u1, self.u2)
649 self.assertNotEqual(self.u1, self.u2)
650 #u1 and anon should have not change perms while u2 should !
650 #u1 and anon should have not change perms while u2 should !
651 u1_auth = AuthUser(user_id=self.u1.user_id)
651 u1_auth = AuthUser(user_id=self.u1.user_id)
652 self.assertEqual(u1_auth.permissions['repositories_groups'],
652 self.assertEqual(u1_auth.permissions['repositories_groups'],
653 {u'group1': u'group.none', u'group2': u'group.none'})
653 {u'group1': u'group.none', u'group2': u'group.none'})
654
654
655 u2_auth = AuthUser(user_id=self.u2.user_id)
655 u2_auth = AuthUser(user_id=self.u2.user_id)
656 self.assertEqual(u2_auth.permissions['repositories_groups'],
656 self.assertEqual(u2_auth.permissions['repositories_groups'],
657 {u'group1': u'group.read', u'group2': u'group.read'})
657 {u'group1': u'group.read', u'group2': u'group.read'})
658
658
659 a1_auth = AuthUser(user_id=self.anon.user_id)
659 a1_auth = AuthUser(user_id=self.anon.user_id)
660 self.assertEqual(a1_auth.permissions['repositories_groups'],
660 self.assertEqual(a1_auth.permissions['repositories_groups'],
661 {u'group1': u'group.none', u'group2': u'group.none'})
661 {u'group1': u'group.none', u'group2': u'group.none'})
662
662
663 def test_repo_group_user_as_user_group_member(self):
663 def test_repo_group_user_as_user_group_member(self):
664 # create Group1
664 # create Group1
665 self.g1 = _make_group('group1', skip_if_exists=True)
665 self.g1 = _make_group('group1', skip_if_exists=True)
666 Session.commit()
666 Session.commit()
667 a1_auth = AuthUser(user_id=self.anon.user_id)
667 a1_auth = AuthUser(user_id=self.anon.user_id)
668
668
669 self.assertEqual(a1_auth.permissions['repositories_groups'],
669 self.assertEqual(a1_auth.permissions['repositories_groups'],
670 {u'group1': u'group.read'})
670 {u'group1': u'group.read'})
671
671
672 # set default permission to none
672 # set default permission to none
673 ReposGroupModel().grant_user_permission(repos_group=self.g1,
673 ReposGroupModel().grant_user_permission(repos_group=self.g1,
674 user=self.anon,
674 user=self.anon,
675 perm='group.none')
675 perm='group.none')
676 # make group
676 # make group
677 self.ug1 = UsersGroupModel().create('G1')
677 self.ug1 = UsersGroupModel().create('G1')
678 # add user to group
678 # add user to group
679 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
679 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
680 Session.commit()
680 Session.commit()
681
681
682 # check if user is in the group
682 # check if user is in the group
683 membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members]
683 membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members]
684 self.assertEqual(membrs, [self.u1.user_id])
684 self.assertEqual(membrs, [self.u1.user_id])
685 # add some user to that group
685 # add some user to that group
686
686
687 # check his permissions
687 # check his permissions
688 a1_auth = AuthUser(user_id=self.anon.user_id)
688 a1_auth = AuthUser(user_id=self.anon.user_id)
689 self.assertEqual(a1_auth.permissions['repositories_groups'],
689 self.assertEqual(a1_auth.permissions['repositories_groups'],
690 {u'group1': u'group.none'})
690 {u'group1': u'group.none'})
691
691
692 u1_auth = AuthUser(user_id=self.u1.user_id)
692 u1_auth = AuthUser(user_id=self.u1.user_id)
693 self.assertEqual(u1_auth.permissions['repositories_groups'],
693 self.assertEqual(u1_auth.permissions['repositories_groups'],
694 {u'group1': u'group.none'})
694 {u'group1': u'group.none'})
695
695
696 # grant ug1 read permissions for
696 # grant ug1 read permissions for
697 ReposGroupModel().grant_users_group_permission(repos_group=self.g1,
697 ReposGroupModel().grant_users_group_permission(repos_group=self.g1,
698 group_name=self.ug1,
698 group_name=self.ug1,
699 perm='group.read')
699 perm='group.read')
700 Session.commit()
700 Session.commit()
701 # check if the
701 # check if the
702 obj = Session.query(UsersGroupRepoGroupToPerm)\
702 obj = Session.query(UsersGroupRepoGroupToPerm)\
703 .filter(UsersGroupRepoGroupToPerm.group == self.g1)\
703 .filter(UsersGroupRepoGroupToPerm.group == self.g1)\
704 .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\
704 .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\
705 .scalar()
705 .scalar()
706 self.assertEqual(obj.permission.permission_name, 'group.read')
706 self.assertEqual(obj.permission.permission_name, 'group.read')
707
707
708 a1_auth = AuthUser(user_id=self.anon.user_id)
708 a1_auth = AuthUser(user_id=self.anon.user_id)
709
709
710 self.assertEqual(a1_auth.permissions['repositories_groups'],
710 self.assertEqual(a1_auth.permissions['repositories_groups'],
711 {u'group1': u'group.none'})
711 {u'group1': u'group.none'})
712
712
713 u1_auth = AuthUser(user_id=self.u1.user_id)
713 u1_auth = AuthUser(user_id=self.u1.user_id)
714 self.assertEqual(u1_auth.permissions['repositories_groups'],
714 self.assertEqual(u1_auth.permissions['repositories_groups'],
715 {u'group1': u'group.read'})
715 {u'group1': u'group.read'})
General Comments 0
You need to be logged in to leave comments. Login now