##// END OF EJS Templates
added tags, and branches to file history select box, fixed annotation changeset errors crash on wrongly given revions
marcink -
r774:c47152c5 beta
parent child Browse files
Show More
@@ -1,218 +1,247 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # files controller for pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 21, 2010
22 22 files controller for pylons
23 23 @author: marcink
24 24 """
25 25 from mercurial import archival
26 26 from pylons import request, response, session, tmpl_context as c, url
27 27 from pylons.i18n.translation import _
28 28 from pylons.controllers.util import redirect
29 29 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
30 30 from rhodecode.lib.base import BaseController, render
31 31 from rhodecode.lib.utils import EmptyChangeset
32 32 from rhodecode.model.scm import ScmModel
33 33 from vcs.exceptions import RepositoryError, ChangesetError
34 34 from vcs.nodes import FileNode
35 35 from vcs.utils import diffs as differ
36 36 import logging
37 37 import rhodecode.lib.helpers as h
38 38 import tempfile
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42 class FilesController(BaseController):
43 43
44 44 @LoginRequired()
45 45 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
46 46 'repository.admin')
47 47 def __before__(self):
48 48 super(FilesController, self).__before__()
49 49 c.file_size_limit = 250 * 1024 #limit of file size to display
50 50
51 51 def index(self, repo_name, revision, f_path):
52 52 hg_model = ScmModel()
53 53 c.repo = hg_model.get_repo(c.repo_name)
54 54 revision = request.POST.get('at_rev', None) or revision
55 55
56 56 def get_next_rev(cur):
57 57 max_rev = len(c.repo.revisions) - 1
58 58 r = cur + 1
59 59 if r > max_rev:
60 60 r = max_rev
61 61 return r
62 62
63 63 def get_prev_rev(cur):
64 64 r = cur - 1
65 65 return r
66 66
67 67 c.f_path = f_path
68 68
69 69
70 70 try:
71 71 c.changeset = c.repo.get_changeset(revision)
72 72 cur_rev = c.changeset.revision
73 73 prev_rev = c.repo.get_changeset(get_prev_rev(cur_rev)).raw_id
74 74 next_rev = c.repo.get_changeset(get_next_rev(cur_rev)).raw_id
75 75
76 76 c.url_prev = url('files_home', repo_name=c.repo_name,
77 77 revision=prev_rev, f_path=f_path)
78 78 c.url_next = url('files_home', repo_name=c.repo_name,
79 79 revision=next_rev, f_path=f_path)
80 80
81 81 try:
82 82 c.files_list = c.changeset.get_node(f_path)
83 83 c.file_history = self._get_history(c.repo, c.files_list, f_path)
84
85 84 except RepositoryError, e:
86 85 h.flash(str(e), category='warning')
87 86 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
88 87
89 88 except RepositoryError, e:
90 89 h.flash(str(e), category='warning')
91 90 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
92 91
93 92
94 93
95 94 return render('files/files.html')
96 95
97 96 def rawfile(self, repo_name, revision, f_path):
98 97 hg_model = ScmModel()
99 98 c.repo = hg_model.get_repo(c.repo_name)
100 99 file_node = c.repo.get_changeset(revision).get_node(f_path)
101 100 response.content_type = file_node.mimetype
102 101 response.content_disposition = 'attachment; filename=%s' \
103 102 % f_path.split('/')[-1]
104 103 return file_node.content
105 104
106 105 def raw(self, repo_name, revision, f_path):
107 106 hg_model = ScmModel()
108 107 c.repo = hg_model.get_repo(c.repo_name)
109 108 file_node = c.repo.get_changeset(revision).get_node(f_path)
110 109 response.content_type = 'text/plain'
111 110
112 111 return file_node.content
113 112
114 113 def annotate(self, repo_name, revision, f_path):
115 114 hg_model = ScmModel()
116 115 c.repo = hg_model.get_repo(c.repo_name)
117 c.cs = c.repo.get_changeset(revision)
118 c.file = c.cs.get_node(f_path)
116
117 try:
118 c.cs = c.repo.get_changeset(revision)
119 c.file = c.cs.get_node(f_path)
120 except RepositoryError, e:
121 h.flash(str(e), category='warning')
122 redirect(h.url('files_home', repo_name=repo_name, revision=revision))
123
119 124 c.file_history = self._get_history(c.repo, c.file, f_path)
120 125
121 126 c.f_path = f_path
122 127
123 128 return render('files/files_annotate.html')
124 129
125 130 def archivefile(self, repo_name, revision, fileformat):
126 131 archive_specs = {
127 132 '.tar.bz2': ('application/x-tar', 'tbz2'),
128 133 '.tar.gz': ('application/x-tar', 'tgz'),
129 134 '.zip': ('application/zip', 'zip'),
130 135 }
131 136 if not archive_specs.has_key(fileformat):
132 137 return 'Unknown archive type %s' % fileformat
133 138
134 139 def read_in_chunks(file_object, chunk_size=1024 * 40):
135 140 """Lazy function (generator) to read a file piece by piece.
136 141 Default chunk size: 40k."""
137 142 while True:
138 143 data = file_object.read(chunk_size)
139 144 if not data:
140 145 break
141 146 yield data
142 147
143 148 archive = tempfile.TemporaryFile()
144 149 repo = ScmModel().get_repo(repo_name).repo
145 150 fname = '%s-%s%s' % (repo_name, revision, fileformat)
146 151 archival.archive(repo, archive, revision, archive_specs[fileformat][1],
147 152 prefix='%s-%s' % (repo_name, revision))
148 153 response.content_type = archive_specs[fileformat][0]
149 154 response.content_disposition = 'attachment; filename=%s' % fname
150 155 archive.seek(0)
151 156 return read_in_chunks(archive)
152 157
153 158 def diff(self, repo_name, f_path):
154 159 hg_model = ScmModel()
155 160 diff1 = request.GET.get('diff1')
156 161 diff2 = request.GET.get('diff2')
157 162 c.action = request.GET.get('diff')
158 163 c.no_changes = diff1 == diff2
159 164 c.f_path = f_path
160 165 c.repo = hg_model.get_repo(c.repo_name)
161 166
162 167 try:
163 168 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
164 169 c.changeset_1 = c.repo.get_changeset(diff1)
165 170 node1 = c.changeset_1.get_node(f_path)
166 171 else:
167 172 c.changeset_1 = EmptyChangeset()
168 173 node1 = FileNode('.', '', changeset=c.changeset_1)
169 174
170 175 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
171 176 c.changeset_2 = c.repo.get_changeset(diff2)
172 177 node2 = c.changeset_2.get_node(f_path)
173 178 else:
174 179 c.changeset_2 = EmptyChangeset()
175 180 node2 = FileNode('.', '', changeset=c.changeset_2)
176 181 except RepositoryError:
177 182 return redirect(url('files_home',
178 183 repo_name=c.repo_name, f_path=f_path))
179 184
180 185 f_udiff = differ.get_udiff(node1, node2)
181 186 diff = differ.DiffProcessor(f_udiff)
182 187
183 188 if c.action == 'download':
184 189 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
185 190 response.content_type = 'text/plain'
186 191 response.content_disposition = 'attachment; filename=%s' \
187 192 % diff_name
188 193 return diff.raw_diff()
189 194
190 195 elif c.action == 'raw':
191 196 response.content_type = 'text/plain'
192 197 return diff.raw_diff()
193 198
194 199 elif c.action == 'diff':
195 200 if node1.size > c.file_size_limit or node2.size > c.file_size_limit:
196 201 c.cur_diff = _('Diff is to big to display')
197 202 else:
198 203 c.cur_diff = diff.as_html()
199 204 else:
200 205 #default option
201 206 if node1.size > c.file_size_limit or node2.size > c.file_size_limit:
202 207 c.cur_diff = _('Diff is to big to display')
203 208 else:
204 209 c.cur_diff = diff.as_html()
205 210
206 211 if not c.cur_diff: c.no_changes = True
207 212 return render('files/file_diff.html')
208 213
209 214 def _get_history(self, repo, node, f_path):
210 215 from vcs.nodes import NodeKind
211 216 if not node.kind is NodeKind.FILE:
212 217 return []
213 218 changesets = node.history
214 219 hist_l = []
220
221 changesets_group = ([], _("Changesets"))
222 branches_group = ([], _("Branches"))
223 tags_group = ([], _("Tags"))
224
215 225 for chs in changesets:
216 226 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
217 hist_l.append((chs.raw_id, n_desc,))
227 changesets_group[0].append((chs.raw_id, n_desc,))
228
229 hist_l.append(changesets_group)
230
231 for name, chs in c.repository_branches.items():
232 #chs = chs.split(':')[-1]
233 branches_group[0].append((chs, name),)
234 hist_l.append(branches_group)
235
236 for name, chs in c.repository_tags.items():
237 #chs = chs.split(':')[-1]
238 tags_group[0].append((chs, name),)
239 hist_l.append(tags_group)
240
218 241 return hist_l
242
243 # [
244 # ([("u1", "User1"), ("u2", "User2")], "Users"),
245 # ([("g1", "Group1"), ("g2", "Group2")], "Groups")
246 # ]
247
General Comments 0
You need to be logged in to leave comments. Login now