diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -1,8 +1,15 @@ -#!/usr/bin/env python -# encoding: utf-8 -# files controller for pylons -# Copyright (C) 2009-2010 Marcin Kuzminski +# -*- coding: utf-8 -*- +""" + rhodecode.controllers.files + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Files controller for RhodeCode + + :created_on: Apr 21, 2010 + :author: marcink + :copyright: (C) 2009-2010 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2 @@ -17,107 +24,115 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. -""" -Created on April 21, 2010 -files controller for pylons -@author: marcink -""" +import tempfile +import logging +import rhodecode.lib.helpers as h + from mercurial import archival + from pylons import request, response, session, tmpl_context as c, url from pylons.i18n.translation import _ from pylons.controllers.util import redirect + from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator from rhodecode.lib.base import BaseController, render from rhodecode.lib.utils import EmptyChangeset -from rhodecode.model.hg_model import HgModel +from rhodecode.model.scm import ScmModel + from vcs.exceptions import RepositoryError, ChangesetError from vcs.nodes import FileNode from vcs.utils import diffs as differ -import logging -import rhodecode.lib.helpers as h -import tempfile - + log = logging.getLogger(__name__) class FilesController(BaseController): - + @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', - 'repository.admin') + 'repository.admin') def __before__(self): super(FilesController, self).__before__() - c.file_size_limit = 250 * 1024 #limit of file size to display + c.cut_off_limit = self.cut_off_limit def index(self, repo_name, revision, f_path): - hg_model = HgModel() - c.repo = repo = hg_model.get_repo(c.repo_name) + hg_model = ScmModel() + c.repo = hg_model.get_repo(c.repo_name) revision = request.POST.get('at_rev', None) or revision - + def get_next_rev(cur): max_rev = len(c.repo.revisions) - 1 r = cur + 1 if r > max_rev: r = max_rev return r - + def get_prev_rev(cur): r = cur - 1 return r c.f_path = f_path - - + + try: - cur_rev = repo.get_changeset(revision).revision - prev_rev = repo.get_changeset(get_prev_rev(cur_rev)).short_id - next_rev = repo.get_changeset(get_next_rev(cur_rev)).short_id - + c.changeset = c.repo.get_changeset(revision) + cur_rev = c.changeset.revision + prev_rev = c.repo.get_changeset(get_prev_rev(cur_rev)).raw_id + next_rev = c.repo.get_changeset(get_next_rev(cur_rev)).raw_id + c.url_prev = url('files_home', repo_name=c.repo_name, - revision=prev_rev, f_path=f_path) + revision=prev_rev, f_path=f_path) c.url_next = url('files_home', repo_name=c.repo_name, - revision=next_rev, f_path=f_path) - - c.changeset = repo.get_changeset(revision) - - c.cur_rev = c.changeset.short_id - c.rev_nr = c.changeset.revision - c.files_list = c.changeset.get_node(f_path) - c.file_history = self._get_history(repo, c.files_list, f_path) - - except (RepositoryError, ChangesetError): - c.files_list = None - + revision=next_rev, f_path=f_path) + + try: + c.files_list = c.changeset.get_node(f_path) + c.file_history = self._get_history(c.repo, c.files_list, f_path) + except RepositoryError, e: + h.flash(str(e), category='warning') + redirect(h.url('files_home', repo_name=repo_name, revision=revision)) + + except RepositoryError, e: + h.flash(str(e), category='warning') + redirect(h.url('files_home', repo_name=repo_name, revision='tip')) + + + return render('files/files.html') def rawfile(self, repo_name, revision, f_path): - hg_model = HgModel() + hg_model = ScmModel() c.repo = hg_model.get_repo(c.repo_name) file_node = c.repo.get_changeset(revision).get_node(f_path) response.content_type = file_node.mimetype response.content_disposition = 'attachment; filename=%s' \ - % f_path.split('/')[-1] + % f_path.split('/')[-1] return file_node.content def raw(self, repo_name, revision, f_path): - hg_model = HgModel() + hg_model = ScmModel() c.repo = hg_model.get_repo(c.repo_name) file_node = c.repo.get_changeset(revision).get_node(f_path) response.content_type = 'text/plain' - + return file_node.content - + def annotate(self, repo_name, revision, f_path): - hg_model = HgModel() + hg_model = ScmModel() c.repo = hg_model.get_repo(c.repo_name) - cs = c.repo.get_changeset(revision) - c.file = cs.get_node(f_path) - c.file_msg = cs.get_file_message(f_path) - c.cur_rev = cs.short_id - c.rev_nr = cs.revision + + try: + c.cs = c.repo.get_changeset(revision) + c.file = c.cs.get_node(f_path) + except RepositoryError, e: + h.flash(str(e), category='warning') + redirect(h.url('files_home', repo_name=repo_name, revision=revision)) + + c.file_history = self._get_history(c.repo, c.file, f_path) + c.f_path = f_path return render('files/files_annotate.html') - + def archivefile(self, repo_name, revision, fileformat): archive_specs = { '.tar.bz2': ('application/x-tar', 'tbz2'), @@ -126,7 +141,7 @@ class FilesController(BaseController): } if not archive_specs.has_key(fileformat): return 'Unknown archive type %s' % fileformat - + def read_in_chunks(file_object, chunk_size=1024 * 40): """Lazy function (generator) to read a file piece by piece. Default chunk size: 40k.""" @@ -134,10 +149,10 @@ class FilesController(BaseController): data = file_object.read(chunk_size) if not data: break - yield data - + yield data + archive = tempfile.TemporaryFile() - repo = HgModel().get_repo(repo_name).repo + repo = ScmModel().get_repo(repo_name).repo fname = '%s-%s%s' % (repo_name, revision, fileformat) archival.archive(repo, archive, revision, archive_specs[fileformat][1], prefix='%s-%s' % (repo_name, revision)) @@ -145,9 +160,9 @@ class FilesController(BaseController): response.content_disposition = 'attachment; filename=%s' % fname archive.seek(0) return read_in_chunks(archive) - + def diff(self, repo_name, f_path): - hg_model = HgModel() + hg_model = ScmModel() diff1 = request.GET.get('diff1') diff2 = request.GET.get('diff2') c.action = request.GET.get('diff') @@ -162,7 +177,7 @@ class FilesController(BaseController): else: c.changeset_1 = EmptyChangeset() node1 = FileNode('.', '', changeset=c.changeset_1) - + if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.repo.get_changeset(diff2) node2 = c.changeset_2.get_node(f_path) @@ -173,43 +188,66 @@ class FilesController(BaseController): return redirect(url('files_home', repo_name=c.repo_name, f_path=f_path)) - c.diff1 = 'r%s:%s' % (c.changeset_1.revision, c.changeset_1.short_id) - c.diff2 = 'r%s:%s' % (c.changeset_2.revision, c.changeset_2.short_id) - f_udiff = differ.get_udiff(node1, node2) diff = differ.DiffProcessor(f_udiff) - + if c.action == 'download': diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = 'attachment; filename=%s' \ - % diff_name + % diff_name return diff.raw_diff() - + elif c.action == 'raw': - c.cur_diff = '
%s
' % h.escape(diff.raw_diff()) + response.content_type = 'text/plain' + return diff.raw_diff() + elif c.action == 'diff': - if node1.size > c.file_size_limit or node2.size > c.file_size_limit: + if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit: c.cur_diff = _('Diff is to big to display') else: c.cur_diff = diff.as_html() else: #default option - if node1.size > c.file_size_limit or node2.size > c.file_size_limit: + if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit: c.cur_diff = _('Diff is to big to display') else: c.cur_diff = diff.as_html() - - if not c.cur_diff: c.no_changes = True + + if not c.cur_diff: c.no_changes = True return render('files/file_diff.html') - + def _get_history(self, repo, node, f_path): from vcs.nodes import NodeKind if not node.kind is NodeKind.FILE: return [] changesets = node.history hist_l = [] + + changesets_group = ([], _("Changesets")) + branches_group = ([], _("Branches")) + tags_group = ([], _("Tags")) + for chs in changesets: n_desc = 'r%s:%s' % (chs.revision, chs.short_id) - hist_l.append((chs.short_id, n_desc,)) + changesets_group[0].append((chs.raw_id, n_desc,)) + + hist_l.append(changesets_group) + + for name, chs in c.repository_branches.items(): + #chs = chs.split(':')[-1] + branches_group[0].append((chs, name),) + hist_l.append(branches_group) + + for name, chs in c.repository_tags.items(): + #chs = chs.split(':')[-1] + tags_group[0].append((chs, name),) + hist_l.append(tags_group) + return hist_l + +# [ +# ([("u1", "User1"), ("u2", "User2")], "Users"), +# ([("g1", "Group1"), ("g2", "Group2")], "Groups") +# ] +