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 |
|
|
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 |
|
|
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.r |
|
|
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 | » |
|
12 | 12 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} |
|
13 | 13 | » |
|
14 | ${_('shortlog')} | |
|
14 | %if c.file_history: | |
|
15 | ${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))} | |
|
16 | » | |
|
17 | ${c.file_history} | |
|
18 | %else: | |
|
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', |
|
|
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