##// END OF EJS Templates
Implemented file history page for showing detailed changelog for a given file...
marcink -
r3039:a520d542 beta
parent child Browse files
Show More
@@ -514,6 +514,10 b' def make_map(config):'
514 514 rmap.connect('shortlog_home', '/{repo_name:.*?}/shortlog',
515 515 controller='shortlog', conditions=dict(function=check_repo))
516 516
517 rmap.connect('shortlog_file_home', '/{repo_name:.*?}/shortlog/{revision}/{f_path:.*}',
518 controller='shortlog', f_path=None,
519 conditions=dict(function=check_repo))
520
517 521 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
518 522 controller='branches', conditions=dict(function=check_repo))
519 523
@@ -26,12 +26,16 b''
26 26 import logging
27 27
28 28 from pylons import tmpl_context as c, request, url
29 from pylons.i18n.translation import _
29 30
31 from rhodecode.lib import helpers as h
30 32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
31 33 from rhodecode.lib.base import BaseRepoController, render
32 34 from rhodecode.lib.helpers import RepoPage
33 35 from pylons.controllers.util import redirect
34 36 from rhodecode.lib.utils2 import safe_int
37 from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError, ChangesetError,\
38 RepositoryError
35 39
36 40 log = logging.getLogger(__name__)
37 41
@@ -44,19 +48,53 b' class ShortlogController(BaseRepoControl'
44 48 def __before__(self):
45 49 super(ShortlogController, self).__before__()
46 50
47 def index(self, repo_name):
51 def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
52 """
53 Safe way to get changeset if error occur it redirects to tip with
54 proper message
55
56 :param rev: revision to fetch
57 :param repo_name: repo name to redirect after
58 """
59
60 try:
61 return c.rhodecode_repo.get_changeset(rev)
62 except RepositoryError, e:
63 h.flash(str(e), category='warning')
64 redirect(h.url('shortlog_home', repo_name=repo_name))
65
66 def index(self, repo_name, revision=None, f_path=None):
48 67 p = safe_int(request.params.get('page', 1), 1)
49 68 size = safe_int(request.params.get('size', 20), 20)
50 69
51 70 def url_generator(**kw):
52 71 return url('shortlog_home', repo_name=repo_name, size=size, **kw)
53 72
54 c.repo_changesets = RepoPage(c.rhodecode_repo, page=p,
73 collection = c.rhodecode_repo
74 c.file_history = f_path
75 if f_path:
76 f_path = f_path.lstrip('/')
77 # get the history for the file !
78 tip_cs = c.rhodecode_repo.get_changeset()
79 try:
80 collection = tip_cs.get_file_history(f_path)
81 except (NodeDoesNotExistError, ChangesetError):
82 #this node is not present at tip !
83 try:
84 cs = self.__get_cs_or_redirect(revision, repo_name)
85 collection = cs.get_file_history(f_path)
86 except RepositoryError, e:
87 h.flash(str(e), category='warning')
88 redirect(h.url('shortlog_home', repo_name=repo_name))
89 collection = list(reversed(collection))
90
91 c.repo_changesets = RepoPage(collection, page=p,
55 92 items_per_page=size, url=url_generator)
56 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
93 page_revisions = [x.raw_id for x in list(collection)]
57 94 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
58 95
59 96 if not c.repo_changesets:
97 h.flash(_('There are no changesets yet'), category='warning')
60 98 return redirect(url('summary_home', repo_name=repo_name))
61 99
62 100 c.shortlog_data = render('shortlog/shortlog_data.html')
@@ -162,6 +162,13 b' class GitChangeset(BaseChangeset):'
162 162 elif isinstance(obj, objects.Tree):
163 163 return NodeKind.DIR
164 164
165 def _get_filectx(self, path):
166 path = self._fix_path(path)
167 if self._get_kind(path) != NodeKind.FILE:
168 raise ChangesetError("File does not exist for revision %r at "
169 " %r" % (self.raw_id, path))
170 return path
171
165 172 def _get_file_nodes(self):
166 173 return chain(*(t[2] for t in self.walk()))
167 174
@@ -264,6 +271,7 b' class GitChangeset(BaseChangeset):'
264 271 which is generally not good. Should be replaced with algorithm
265 272 iterating commits.
266 273 """
274 self._get_filectx(path)
267 275 cmd = 'log --pretty="format: %%H" -s -p %s -- "%s"' % (
268 276 self.id, path
269 277 )
@@ -181,7 +181,7 b' class MercurialChangeset(BaseChangeset):'
181 181 path = self._fix_path(path)
182 182 if self._get_kind(path) != NodeKind.FILE:
183 183 raise ChangesetError("File does not exist for revision %r at "
184 " %r" % (self.revision, path))
184 " %r" % (self.raw_id, path))
185 185 return self._ctx.filectx(path)
186 186
187 187 def _extract_submodules(self):
@@ -2650,15 +2650,14 b' h3.files_location {'
2650 2650 #graph_content .container .mid .message a:hover{
2651 2651 text-decoration: none;
2652 2652 }
2653 #content #graph_content .message .revision-link,
2654 #changeset_content .container .message .revision-link
2653
2654 .revision-link
2655 2655 {
2656 2656 color:#3F6F9F;
2657 2657 font-weight: bold !important;
2658 2658 }
2659 2659
2660 #content #graph_content .message .issue-tracker-link,
2661 #changeset_content .container .message .issue-tracker-link{
2660 .issue-tracker-link{
2662 2661 color:#3F6F9F;
2663 2662 font-weight: bold !important;
2664 2663 }
@@ -8,6 +8,7 b''
8 8 ${h.select('diff1',c.file_changeset.raw_id,c.file_history)}
9 9 ${h.submit('diff',_('diff to revision'),class_="ui-btn")}
10 10 ${h.submit('show_rev',_('show at revision'),class_="ui-btn")}
11 ${h.link_to(_('show full history'),h.url('shortlog_file_home',repo_name=c.repo_name, revision=c.file_changeset.raw_id, f_path=c.f_path),class_="ui-btn")}
11 12 ${h.hidden('annotate', c.annotate)}
12 13 ${h.end_form()}
13 14 </div>
@@ -11,7 +11,13 b''
11 11 &raquo;
12 12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 13 &raquo;
14 %if c.file_history:
15 ${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}
16 &raquo;
17 ${c.file_history}
18 %else:
14 19 ${_('shortlog')}
20 %endif
15 21 </%def>
16 22
17 23 <%def name="page_nav()">
@@ -30,9 +30,7 b''
30 30 </div>
31 31 </td>
32 32 <td>
33 ${h.link_to(h.truncate(cs.message,50) or _('No commit message'),
34 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
35 title=cs.message)}
33 ${h.urlify_commit(h.truncate(cs.message,50),c.repo_name, h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
36 34 </td>
37 35 <td><span class="tooltip" title="${h.tooltip(h.fmt_date(cs.date))}">
38 36 ${h.age(cs.date)}</span>
@@ -1,8 +1,65 b''
1 1 from rhodecode.tests import *
2 2
3
3 4 class TestShortlogController(TestController):
4 5
5 def test_index(self):
6 def test_index_hg(self):
7 self.log_user()
8 response = self.app.get(url(controller='shortlog', action='index',
9 repo_name=HG_REPO))
10 # Test response...
11
12 def test_index_git(self):
13 self.log_user()
14 response = self.app.get(url(controller='shortlog', action='index',
15 repo_name=GIT_REPO))
16 # Test response...
17
18 def test_index_hg_with_filenode(self):
19 self.log_user()
20 response = self.app.get(url(controller='shortlog', action='index',
21 revision='tip', f_path='/vcs/exceptions.py',
22 repo_name=HG_REPO))
23 #history commits messages
24 response.mustcontain('Added exceptions module, this time for real')
25 response.mustcontain('Added not implemented hg backend test case')
26 response.mustcontain('Added BaseChangeset class')
27 # Test response...
28
29 def test_index_git_with_filenode(self):
6 30 self.log_user()
7 response = self.app.get(url(controller='shortlog', action='index',repo_name=HG_REPO))
8 # Test response...
31 response = self.app.get(url(controller='shortlog', action='index',
32 revision='tip', f_path='/vcs/exceptions.py',
33 repo_name=GIT_REPO))
34 #history commits messages
35 response.mustcontain('Added exceptions module, this time for real')
36 response.mustcontain('Added not implemented hg backend test case')
37 response.mustcontain('Added BaseChangeset class')
38
39 def test_index_hg_with_filenode_that_is_dirnode(self):
40 self.log_user()
41 response = self.app.get(url(controller='shortlog', action='index',
42 revision='tip', f_path='/tests',
43 repo_name=HG_REPO))
44 self.assertEqual(response.status, '302 Found')
45
46 def test_index_git_with_filenode_that_is_dirnode(self):
47 self.log_user()
48 response = self.app.get(url(controller='shortlog', action='index',
49 revision='tip', f_path='/tests',
50 repo_name=GIT_REPO))
51 self.assertEqual(response.status, '302 Found')
52
53 def test_index_hg_with_filenode_not_existing(self):
54 self.log_user()
55 response = self.app.get(url(controller='shortlog', action='index',
56 revision='tip', f_path='/wrong_path',
57 repo_name=HG_REPO))
58 self.assertEqual(response.status, '302 Found')
59
60 def test_index_git_with_filenode_not_existing(self):
61 self.log_user()
62 response = self.app.get(url(controller='shortlog', action='index',
63 revision='tip', f_path='/wrong_path',
64 repo_name=GIT_REPO))
65 self.assertEqual(response.status, '302 Found')
General Comments 0
You need to be logged in to leave comments. Login now