##// END OF EJS Templates
added os.sep for files controller...
marcink -
r1200:3ecaa17d beta
parent child Browse files
Show More
@@ -1,282 +1,283 b''
1 1 .. _changelog:
2 2
3 3 Changelog
4 4 =========
5 5
6 6 1.2.0 (**2011-XX-XX**)
7 7 ======================
8 8
9 9 :status: in-progress
10 10 :branch: beta
11 11
12 12 news
13 13 ----
14 14
15 15 - implemented #89 Can setup google analytics code from settings menu
16 16 - implemented #91 added nicer looking archive urls with more download options
17 17 like tags, branches
18 18 - implemented #44 into file browsing, and added follow branch option
19 19 - implemented #84 downloads can be enabled/disabled for each repository
20 20 - anonymous repository can be cloned without having to pass default:default
21 21 into clone url
22 22 - fixed #90 whoosh indexer can index chooses repositories passed in command
23 23 line
24 24 - extended journal with day aggregates and paging
25 - implemented #107 customizable code highlights on code sources
25 - implemented #107 source code lines highlight ranges
26 26 - implemented #93 customizable changelog on combined revision ranges -
27 27 equivalent of githubs compare view
28 28 - implemented #108 extended and more powerful LDAP configuration
29 29 - implemented #56 users groups
30 30 - major code rewrites optimized codes for speed and memory usage
31 31 - raw and diff downloads are now in git format
32 32 - setup command checks for write access to given path
33 33 - fixed many issues with international characters and unicode. It uses utf8
34 34 decode with replace to provide less errors even with non utf8 encoded strings
35 35 - #125 added API KEY access to feeds
36 - #109 Repository can be created from external Mercurial link, and manually
37 updated (via pull) from admin panel
36 - #109 Repository can be created from external Mercurial link (aka. remote
37 repository, and manually updated (via pull) from admin panel
38 38
39 39 fixes
40 40 -----
41 41
42 42 - fixed file browser bug, when switching into given form revision the url was
43 43 not changing
44 44 - fixed propagation to error controller on simplehg and simplegit middlewares
45 45 - fixed error when trying to make a download on empty repository
46 46 - fixed problem with '[' chars in commit messages in journal
47 47 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
48 48 - journal fork fixes
49 49 - removed issue with space inside renamed repository after deletion
50 50 - fixed strange issue on formencode imports
51 51 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
52 - windows fixes for os.kill and path spliting, issues #148 and #133
52 53
53 54 1.1.7 (**2011-03-23**)
54 55 ======================
55 56
56 57 news
57 58 ----
58 59
59 60 fixes
60 61 -----
61 62
62 63 - fixed (again) #136 installation support for FreeBSD
63 64
64 65
65 66 1.1.6 (**2011-03-21**)
66 67 ======================
67 68
68 69 news
69 70 ----
70 71
71 72 fixes
72 73 -----
73 74
74 75 - fixed #136 installation support for FreeBSD
75 76 - RhodeCode will check for python version during installation
76 77
77 78 1.1.5 (**2011-03-17**)
78 79 ======================
79 80
80 81 news
81 82 ----
82 83
83 84 - basic windows support, by exchanging pybcrypt into sha256 for windows only
84 85 highly inspired by idea of mantis406
85 86
86 87 fixes
87 88 -----
88 89
89 90 - fixed sorting by author in main page
90 91 - fixed crashes with diffs on binary files
91 92 - fixed #131 problem with boolean values for LDAP
92 93 - fixed #122 mysql problems thanks to striker69
93 94 - fixed problem with errors on calling raw/raw_files/annotate functions
94 95 with unknown revisions
95 96 - fixed returned rawfiles attachment names with international character
96 97 - cleaned out docs, big thanks to Jason Harris
97 98
98 99 1.1.4 (**2011-02-19**)
99 100 ======================
100 101
101 102 news
102 103 ----
103 104
104 105 fixes
105 106 -----
106 107
107 108 - fixed formencode import problem on settings page, that caused server crash
108 109 when that page was accessed as first after server start
109 110 - journal fixes
110 111 - fixed option to access repository just by entering http://server/<repo_name>
111 112
112 113 1.1.3 (**2011-02-16**)
113 114 ======================
114 115
115 116 news
116 117 ----
117 118
118 119 - implemented #102 allowing the '.' character in username
119 120 - added option to access repository just by entering http://server/<repo_name>
120 121 - celery task ignores result for better performance
121 122
122 123 fixes
123 124 -----
124 125
125 126 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
126 127 apollo13 and Johan Walles
127 128 - small fixes in journal
128 129 - fixed problems with getting setting for celery from .ini files
129 130 - registration, password reset and login boxes share the same title as main
130 131 application now
131 132 - fixed #113: to high permissions to fork repository
132 133 - fixed problem with '[' chars in commit messages in journal
133 134 - removed issue with space inside renamed repository after deletion
134 135 - db transaction fixes when filesystem repository creation failed
135 136 - fixed #106 relation issues on databases different than sqlite
136 137 - fixed static files paths links to use of url() method
137 138
138 139 1.1.2 (**2011-01-12**)
139 140 ======================
140 141
141 142 news
142 143 ----
143 144
144 145
145 146 fixes
146 147 -----
147 148
148 149 - fixes #98 protection against float division of percentage stats
149 150 - fixed graph bug
150 151 - forced webhelpers version since it was making troubles during installation
151 152
152 153 1.1.1 (**2011-01-06**)
153 154 ======================
154 155
155 156 news
156 157 ----
157 158
158 159 - added force https option into ini files for easier https usage (no need to
159 160 set server headers with this options)
160 161 - small css updates
161 162
162 163 fixes
163 164 -----
164 165
165 166 - fixed #96 redirect loop on files view on repositories without changesets
166 167 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
167 168 and server crashed with errors
168 169 - fixed large tooltips problems on main page
169 170 - fixed #92 whoosh indexer is more error proof
170 171
171 172 1.1.0 (**2010-12-18**)
172 173 ======================
173 174
174 175 news
175 176 ----
176 177
177 178 - rewrite of internals for vcs >=0.1.10
178 179 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
179 180 with older clients
180 181 - anonymous access, authentication via ldap
181 182 - performance upgrade for cached repos list - each repository has it's own
182 183 cache that's invalidated when needed.
183 184 - performance upgrades on repositories with large amount of commits (20K+)
184 185 - main page quick filter for filtering repositories
185 186 - user dashboards with ability to follow chosen repositories actions
186 187 - sends email to admin on new user registration
187 188 - added cache/statistics reset options into repository settings
188 189 - more detailed action logger (based on hooks) with pushed changesets lists
189 190 and options to disable those hooks from admin panel
190 191 - introduced new enhanced changelog for merges that shows more accurate results
191 192 - new improved and faster code stats (based on pygments lexers mapping tables,
192 193 showing up to 10 trending sources for each repository. Additionally stats
193 194 can be disabled in repository settings.
194 195 - gui optimizations, fixed application width to 1024px
195 196 - added cut off (for large files/changesets) limit into config files
196 197 - whoosh, celeryd, upgrade moved to paster command
197 198 - other than sqlite database backends can be used
198 199
199 200 fixes
200 201 -----
201 202
202 203 - fixes #61 forked repo was showing only after cache expired
203 204 - fixes #76 no confirmation on user deletes
204 205 - fixes #66 Name field misspelled
205 206 - fixes #72 block user removal when he owns repositories
206 207 - fixes #69 added password confirmation fields
207 208 - fixes #87 RhodeCode crashes occasionally on updating repository owner
208 209 - fixes #82 broken annotations on files with more than 1 blank line at the end
209 210 - a lot of fixes and tweaks for file browser
210 211 - fixed detached session issues
211 212 - fixed when user had no repos he would see all repos listed in my account
212 213 - fixed ui() instance bug when global hgrc settings was loaded for server
213 214 instance and all hgrc options were merged with our db ui() object
214 215 - numerous small bugfixes
215 216
216 217 (special thanks for TkSoh for detailed feedback)
217 218
218 219
219 220 1.0.2 (**2010-11-12**)
220 221 ======================
221 222
222 223 news
223 224 ----
224 225
225 226 - tested under python2.7
226 227 - bumped sqlalchemy and celery versions
227 228
228 229 fixes
229 230 -----
230 231
231 232 - fixed #59 missing graph.js
232 233 - fixed repo_size crash when repository had broken symlinks
233 234 - fixed python2.5 crashes.
234 235
235 236
236 237 1.0.1 (**2010-11-10**)
237 238 ======================
238 239
239 240 news
240 241 ----
241 242
242 243 - small css updated
243 244
244 245 fixes
245 246 -----
246 247
247 248 - fixed #53 python2.5 incompatible enumerate calls
248 249 - fixed #52 disable mercurial extension for web
249 250 - fixed #51 deleting repositories don't delete it's dependent objects
250 251
251 252
252 253 1.0.0 (**2010-11-02**)
253 254 ======================
254 255
255 256 - security bugfix simplehg wasn't checking for permissions on commands
256 257 other than pull or push.
257 258 - fixed doubled messages after push or pull in admin journal
258 259 - templating and css corrections, fixed repo switcher on chrome, updated titles
259 260 - admin menu accessible from options menu on repository view
260 261 - permissions cached queries
261 262
262 263 1.0.0rc4 (**2010-10-12**)
263 264 ==========================
264 265
265 266 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
266 267 - removed cache_manager settings from sqlalchemy meta
267 268 - added sqlalchemy cache settings to ini files
268 269 - validated password length and added second try of failure on paster setup-app
269 270 - fixed setup database destroy prompt even when there was no db
270 271
271 272
272 273 1.0.0rc3 (**2010-10-11**)
273 274 =========================
274 275
275 276 - fixed i18n during installation.
276 277
277 278 1.0.0rc2 (**2010-10-11**)
278 279 =========================
279 280
280 281 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
281 282 occure. After vcs is fixed it'll be put back again.
282 283 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,303 +1,304 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.files
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Files controller for RhodeCode
7 7
8 8 :created_on: Apr 21, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 import os
28 29 import logging
29 30 import rhodecode.lib.helpers as h
30 31
31 32 from pylons import request, response, session, tmpl_context as c, url
32 33 from pylons.i18n.translation import _
33 34 from pylons.controllers.util import redirect
34 35
35 36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 37 from rhodecode.lib.base import BaseRepoController, render
37 38 from rhodecode.lib.utils import EmptyChangeset
38 39 from rhodecode.model.repo import RepoModel
39 40
40 41 from vcs.backends import ARCHIVE_SPECS
41 42 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
42 43 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
43 44 from vcs.nodes import FileNode, NodeKind
44 45 from vcs.utils import diffs as differ
45 46
46 47 log = logging.getLogger(__name__)
47 48
48 49
49 50 class FilesController(BaseRepoController):
50 51
51 52 @LoginRequired()
52 53 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 54 'repository.admin')
54 55 def __before__(self):
55 56 super(FilesController, self).__before__()
56 57 c.cut_off_limit = self.cut_off_limit
57 58
58 59 def __get_cs_or_redirect(self, rev, repo_name):
59 60 """
60 61 Safe way to get changeset if error occur it redirects to tip with
61 62 proper message
62 63
63 64 :param rev: revision to fetch
64 65 :param repo_name: repo name to redirect after
65 66 """
66 67
67 68 try:
68 69 return c.rhodecode_repo.get_changeset(rev)
69 70 except EmptyRepositoryError, e:
70 71 h.flash(_('There are no files yet'), category='warning')
71 72 redirect(h.url('summary_home', repo_name=repo_name))
72 73
73 74 except RepositoryError, e:
74 75 h.flash(str(e), category='warning')
75 76 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
76 77
77 78
78 79 def __get_filenode_or_redirect(self, repo_name, cs, path):
79 80 """
80 81 Returns file_node, if error occurs or given path is directory,
81 82 it'll redirect to top level path
82 83
83 84 :param repo_name: repo_name
84 85 :param cs: given changeset
85 86 :param path: path to lookup
86 87 """
87 88
88 89
89 90 try:
90 91 file_node = cs.get_node(path)
91 92 if file_node.is_dir():
92 93 raise RepositoryError('given path is a directory')
93 94 except RepositoryError, e:
94 95 h.flash(str(e), category='warning')
95 96 redirect(h.url('files_home', repo_name=repo_name,
96 97 revision=cs.raw_id))
97 98
98 99 return file_node
99 100
100 101 def index(self, repo_name, revision, f_path):
101 102 #reditect to given revision from form if given
102 103 post_revision = request.POST.get('at_rev', None)
103 104 if post_revision:
104 105 cs = self.__get_cs_or_redirect(revision, repo_name)
105 106 redirect(url('files_home', repo_name=c.repo_name,
106 107 revision=cs.raw_id, f_path=f_path))
107 108
108 109
109 110 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
110 111 c.branch = request.GET.get('branch', None)
111 112 c.f_path = f_path
112 113
113 114 cur_rev = c.changeset.revision
114 115
115 116 #prev link
116 117 try:
117 118 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
118 119 c.url_prev = url('files_home', repo_name=c.repo_name,
119 120 revision=prev_rev.raw_id, f_path=f_path)
120 121 if c.branch:
121 122 c.url_prev += '?branch=%s' % c.branch
122 123 except (ChangesetDoesNotExistError, VCSError):
123 124 c.url_prev = '#'
124 125
125 126 #next link
126 127 try:
127 128 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
128 129 c.url_next = url('files_home', repo_name=c.repo_name,
129 130 revision=next_rev.raw_id, f_path=f_path)
130 131 if c.branch:
131 132 c.url_next += '?branch=%s' % c.branch
132 133 except (ChangesetDoesNotExistError, VCSError):
133 134 c.url_next = '#'
134 135
135 136 #files or dirs
136 137 try:
137 138 c.files_list = c.changeset.get_node(f_path)
138 139
139 140 if c.files_list.is_file():
140 141 c.file_history = self._get_node_history(c.changeset, f_path)
141 142 else:
142 143 c.file_history = []
143 144 except RepositoryError, e:
144 145 h.flash(str(e), category='warning')
145 146 redirect(h.url('files_home', repo_name=repo_name,
146 147 revision=revision))
147 148
148 149
149 150 return render('files/files.html')
150 151
151 152 def rawfile(self, repo_name, revision, f_path):
152 153 cs = self.__get_cs_or_redirect(revision, repo_name)
153 154 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
154 155
155 156 response.content_disposition = 'attachment; filename=%s' % \
156 f_path.split('/')[-1].encode('utf8', 'replace')
157 f_path.split(os.sep)[-1].encode('utf8', 'replace')
157 158
158 159 response.content_type = file_node.mimetype
159 160 return file_node.content
160 161
161 162 def raw(self, repo_name, revision, f_path):
162 163 cs = self.__get_cs_or_redirect(revision, repo_name)
163 164 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
164 165
165 166 response.content_type = 'text/plain'
166 167 return file_node.content
167 168
168 169 def annotate(self, repo_name, revision, f_path):
169 170 c.cs = self.__get_cs_or_redirect(revision, repo_name)
170 171 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
171 172
172 173 c.file_history = self._get_node_history(c.cs, f_path)
173 174 c.f_path = f_path
174 175 return render('files/files_annotate.html')
175 176
176 177 def archivefile(self, repo_name, fname):
177 178
178 179 fileformat = None
179 180 revision = None
180 181 ext = None
181 182
182 183 for a_type, ext_data in ARCHIVE_SPECS.items():
183 184 archive_spec = fname.split(ext_data[1])
184 185 if len(archive_spec) == 2 and archive_spec[1] == '':
185 186 fileformat = a_type or ext_data[1]
186 187 revision = archive_spec[0]
187 188 ext = ext_data[1]
188 189
189 190 try:
190 191 dbrepo = RepoModel().get_by_repo_name(repo_name)
191 192 if dbrepo.enable_downloads is False:
192 193 return _('downloads disabled')
193 194
194 195 cs = c.rhodecode_repo.get_changeset(revision)
195 196 content_type = ARCHIVE_SPECS[fileformat][0]
196 197 except ChangesetDoesNotExistError:
197 198 return _('Unknown revision %s') % revision
198 199 except EmptyRepositoryError:
199 200 return _('Empty repository')
200 201 except (ImproperArchiveTypeError, KeyError):
201 202 return _('Unknown archive type')
202 203
203 204 response.content_type = content_type
204 205 response.content_disposition = 'attachment; filename=%s-%s%s' \
205 206 % (repo_name, revision, ext)
206 207
207 208 return cs.get_chunked_archive(stream=None, kind=fileformat)
208 209
209 210
210 211 def diff(self, repo_name, f_path):
211 212 diff1 = request.GET.get('diff1')
212 213 diff2 = request.GET.get('diff2')
213 214 c.action = request.GET.get('diff')
214 215 c.no_changes = diff1 == diff2
215 216 c.f_path = f_path
216 217
217 218 try:
218 219 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
219 220 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
220 221 node1 = c.changeset_1.get_node(f_path)
221 222 else:
222 223 c.changeset_1 = EmptyChangeset()
223 224 node1 = FileNode('.', '', changeset=c.changeset_1)
224 225
225 226 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
226 227 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
227 228 node2 = c.changeset_2.get_node(f_path)
228 229 else:
229 230 c.changeset_2 = EmptyChangeset()
230 231 node2 = FileNode('.', '', changeset=c.changeset_2)
231 232 except RepositoryError:
232 233 return redirect(url('files_home',
233 234 repo_name=c.repo_name, f_path=f_path))
234 235
235 236
236 237 if c.action == 'download':
237 238 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
238 239 format='gitdiff')
239 240
240 241 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
241 242 response.content_type = 'text/plain'
242 243 response.content_disposition = 'attachment; filename=%s' \
243 244 % diff_name
244 245 return diff.raw_diff()
245 246
246 247 elif c.action == 'raw':
247 248 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
248 249 format='gitdiff')
249 250 response.content_type = 'text/plain'
250 251 return diff.raw_diff()
251 252
252 253 elif c.action == 'diff':
253 254
254 255 if node1.is_binary or node2.is_binary:
255 256 c.cur_diff = _('Binary file')
256 257 elif node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
257 258 c.cur_diff = _('Diff is too big to display')
258 259 else:
259 260 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
260 261 format='gitdiff')
261 262 c.cur_diff = diff.as_html()
262 263 else:
263 264
264 265 #default option
265 266 if node1.is_binary or node2.is_binary:
266 267 c.cur_diff = _('Binary file')
267 268 elif node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
268 269 c.cur_diff = _('Diff is too big to display')
269 270 else:
270 271 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
271 272 format='gitdiff')
272 273 c.cur_diff = diff.as_html()
273 274
274 275 if not c.cur_diff:
275 276 c.no_changes = True
276 277 return render('files/file_diff.html')
277 278
278 279 def _get_node_history(self, cs, f_path):
279 280 changesets = cs.get_file_history(f_path)
280 281 hist_l = []
281 282
282 283 changesets_group = ([], _("Changesets"))
283 284 branches_group = ([], _("Branches"))
284 285 tags_group = ([], _("Tags"))
285 286
286 287 for chs in changesets:
287 288 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
288 289 changesets_group[0].append((chs.raw_id, n_desc,))
289 290
290 291 hist_l.append(changesets_group)
291 292
292 293 for name, chs in c.rhodecode_repo.branches.items():
293 294 #chs = chs.split(':')[-1]
294 295 branches_group[0].append((chs, name),)
295 296 hist_l.append(branches_group)
296 297
297 298 for name, chs in c.rhodecode_repo.tags.items():
298 299 #chs = chs.split(':')[-1]
299 300 tags_group[0].append((chs, name),)
300 301 hist_l.append(tags_group)
301 302
302 303 return hist_l
303 304
General Comments 0
You need to be logged in to leave comments. Login now