Show More
@@ -0,0 +1,50 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2011-2017 RhodeCode GmbH | |||
|
4 | # | |||
|
5 | # This program is free software: you can redistribute it and/or modify | |||
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU Affero General Public License | |||
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | import logging | |||
|
21 | ||||
|
22 | from pyramid.httpexceptions import HTTPNotFound | |||
|
23 | from pyramid.view import view_config | |||
|
24 | ||||
|
25 | from rhodecode.apps._base import BaseReferencesView | |||
|
26 | from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator) | |||
|
27 | from rhodecode.lib import helpers as h | |||
|
28 | ||||
|
29 | log = logging.getLogger(__name__) | |||
|
30 | ||||
|
31 | ||||
|
32 | class RepoBookmarksView(BaseReferencesView): | |||
|
33 | ||||
|
34 | @LoginRequired() | |||
|
35 | @HasRepoPermissionAnyDecorator( | |||
|
36 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
37 | @view_config( | |||
|
38 | route_name='bookmarks_home', request_method='GET', | |||
|
39 | renderer='rhodecode:templates/bookmarks/bookmarks.mako') | |||
|
40 | def bookmarks(self): | |||
|
41 | c = self.load_default_context() | |||
|
42 | ||||
|
43 | if not h.is_hg(self.db_repo): | |||
|
44 | raise HTTPNotFound() | |||
|
45 | ||||
|
46 | ref_items = self.rhodecode_vcs_repo.bookmarks.items() | |||
|
47 | self.load_refs_context( | |||
|
48 | ref_items=ref_items, partials_template='bookmarks/bookmarks_data.mako') | |||
|
49 | ||||
|
50 | return self._get_template_context(c) |
@@ -0,0 +1,51 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2011-2017 RhodeCode GmbH | |||
|
4 | # | |||
|
5 | # This program is free software: you can redistribute it and/or modify | |||
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU Affero General Public License | |||
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | ||||
|
21 | import logging | |||
|
22 | from pyramid.view import view_config | |||
|
23 | ||||
|
24 | from rhodecode.apps._base import BaseReferencesView | |||
|
25 | from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator) | |||
|
26 | ||||
|
27 | ||||
|
28 | log = logging.getLogger(__name__) | |||
|
29 | ||||
|
30 | ||||
|
31 | class RepoBranchesView(BaseReferencesView): | |||
|
32 | ||||
|
33 | @LoginRequired() | |||
|
34 | @HasRepoPermissionAnyDecorator( | |||
|
35 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
36 | @view_config( | |||
|
37 | route_name='branches_home', request_method='GET', | |||
|
38 | renderer='rhodecode:templates/branches/branches.mako') | |||
|
39 | def branches(self): | |||
|
40 | c = self.load_default_context() | |||
|
41 | c.closed_branches = self.rhodecode_vcs_repo.branches_closed | |||
|
42 | # NOTE(marcink): | |||
|
43 | # we need this trick because of PartialRenderer still uses the | |||
|
44 | # global 'c', we might not need this after full pylons migration | |||
|
45 | self._register_global_c(c) | |||
|
46 | ||||
|
47 | ref_items = self.rhodecode_vcs_repo.branches_all.items() | |||
|
48 | self.load_refs_context( | |||
|
49 | ref_items=ref_items, partials_template='branches/branches_data.mako') | |||
|
50 | ||||
|
51 | return self._get_template_context(c) |
@@ -0,0 +1,45 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2011-2017 RhodeCode GmbH | |||
|
4 | # | |||
|
5 | # This program is free software: you can redistribute it and/or modify | |||
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU Affero General Public License | |||
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | ||||
|
21 | import logging | |||
|
22 | from pyramid.view import view_config | |||
|
23 | ||||
|
24 | from rhodecode.apps._base import BaseReferencesView | |||
|
25 | from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator) | |||
|
26 | ||||
|
27 | log = logging.getLogger(__name__) | |||
|
28 | ||||
|
29 | ||||
|
30 | class RepoTagsView(BaseReferencesView): | |||
|
31 | ||||
|
32 | @LoginRequired() | |||
|
33 | @HasRepoPermissionAnyDecorator( | |||
|
34 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
35 | @view_config( | |||
|
36 | route_name='tags_home', request_method='GET', | |||
|
37 | renderer='rhodecode:templates/tags/tags.mako') | |||
|
38 | def tags(self): | |||
|
39 | c = self.load_default_context() | |||
|
40 | ||||
|
41 | ref_items = self.rhodecode_vcs_repo.tags.items() | |||
|
42 | self.load_refs_context( | |||
|
43 | ref_items=ref_items, partials_template='tags/tags_data.mako') | |||
|
44 | ||||
|
45 | return self._get_template_context(c) |
@@ -24,8 +24,10 b' from pylons import tmpl_context as c' | |||||
24 | from pyramid.httpexceptions import HTTPFound |
|
24 | from pyramid.httpexceptions import HTTPFound | |
25 |
|
25 | |||
26 | from rhodecode.lib import helpers as h |
|
26 | from rhodecode.lib import helpers as h | |
27 |
from rhodecode.lib.utils |
|
27 | from rhodecode.lib.utils import PartialRenderer | |
|
28 | from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time | |||
28 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError |
|
29 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError | |
|
30 | from rhodecode.lib.ext_json import json | |||
29 | from rhodecode.model import repo |
|
31 | from rhodecode.model import repo | |
30 | from rhodecode.model.db import User |
|
32 | from rhodecode.model.db import User | |
31 | from rhodecode.model.scm import ScmModel |
|
33 | from rhodecode.model.scm import ScmModel | |
@@ -37,6 +39,24 b" ADMIN_PREFIX = '/_admin'" | |||||
37 | STATIC_FILE_PREFIX = '/_static' |
|
39 | STATIC_FILE_PREFIX = '/_static' | |
38 |
|
40 | |||
39 |
|
41 | |||
|
42 | def get_format_ref_id(repo): | |||
|
43 | """Returns a `repo` specific reference formatter function""" | |||
|
44 | if h.is_svn(repo): | |||
|
45 | return _format_ref_id_svn | |||
|
46 | else: | |||
|
47 | return _format_ref_id | |||
|
48 | ||||
|
49 | ||||
|
50 | def _format_ref_id(name, raw_id): | |||
|
51 | """Default formatting of a given reference `name`""" | |||
|
52 | return name | |||
|
53 | ||||
|
54 | ||||
|
55 | def _format_ref_id_svn(name, raw_id): | |||
|
56 | """Special way of formatting a reference for Subversion including path""" | |||
|
57 | return '%s@%s' % (name, raw_id) | |||
|
58 | ||||
|
59 | ||||
40 | class TemplateArgs(StrictAttributeDict): |
|
60 | class TemplateArgs(StrictAttributeDict): | |
41 | pass |
|
61 | pass | |
42 |
|
62 | |||
@@ -170,6 +190,56 b' class DataGridAppView(object):' | |||||
170 | return draw, start, length |
|
190 | return draw, start, length | |
171 |
|
191 | |||
172 |
|
192 | |||
|
193 | class BaseReferencesView(RepoAppView): | |||
|
194 | """ | |||
|
195 | Base for reference view for branches, tags and bookmarks. | |||
|
196 | """ | |||
|
197 | def load_default_context(self): | |||
|
198 | c = self._get_local_tmpl_context() | |||
|
199 | ||||
|
200 | # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead | |||
|
201 | c.repo_info = self.db_repo | |||
|
202 | ||||
|
203 | self._register_global_c(c) | |||
|
204 | return c | |||
|
205 | ||||
|
206 | def load_refs_context(self, ref_items, partials_template): | |||
|
207 | _render = PartialRenderer(partials_template) | |||
|
208 | _data = [] | |||
|
209 | pre_load = ["author", "date", "message"] | |||
|
210 | ||||
|
211 | is_svn = h.is_svn(self.rhodecode_vcs_repo) | |||
|
212 | format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo) | |||
|
213 | ||||
|
214 | for ref_name, commit_id in ref_items: | |||
|
215 | commit = self.rhodecode_vcs_repo.get_commit( | |||
|
216 | commit_id=commit_id, pre_load=pre_load) | |||
|
217 | ||||
|
218 | # TODO: johbo: Unify generation of reference links | |||
|
219 | use_commit_id = '/' in ref_name or is_svn | |||
|
220 | files_url = h.url( | |||
|
221 | 'files_home', | |||
|
222 | repo_name=c.repo_name, | |||
|
223 | f_path=ref_name if is_svn else '', | |||
|
224 | revision=commit_id if use_commit_id else ref_name, | |||
|
225 | at=ref_name) | |||
|
226 | ||||
|
227 | _data.append({ | |||
|
228 | "name": _render('name', ref_name, files_url), | |||
|
229 | "name_raw": ref_name, | |||
|
230 | "date": _render('date', commit.date), | |||
|
231 | "date_raw": datetime_to_time(commit.date), | |||
|
232 | "author": _render('author', commit.author), | |||
|
233 | "commit": _render( | |||
|
234 | 'commit', commit.message, commit.raw_id, commit.idx), | |||
|
235 | "commit_raw": commit.idx, | |||
|
236 | "compare": _render( | |||
|
237 | 'compare', format_ref_id(ref_name, commit.raw_id)), | |||
|
238 | }) | |||
|
239 | c.has_references = bool(_data) | |||
|
240 | c.data = json.dumps(_data) | |||
|
241 | ||||
|
242 | ||||
173 | class RepoRoutePredicate(object): |
|
243 | class RepoRoutePredicate(object): | |
174 | def __init__(self, val, config): |
|
244 | def __init__(self, val, config): | |
175 | self.val = val |
|
245 | self.val = val |
@@ -21,6 +21,21 b'' | |||||
21 |
|
21 | |||
22 | def includeme(config): |
|
22 | def includeme(config): | |
23 |
|
23 | |||
|
24 | # Tags | |||
|
25 | config.add_route( | |||
|
26 | name='tags_home', | |||
|
27 | pattern='/{repo_name:.*?[^/]}/tags', repo_route=True) | |||
|
28 | ||||
|
29 | # Branches | |||
|
30 | config.add_route( | |||
|
31 | name='branches_home', | |||
|
32 | pattern='/{repo_name:.*?[^/]}/branches', repo_route=True) | |||
|
33 | ||||
|
34 | # Bookmarks | |||
|
35 | config.add_route( | |||
|
36 | name='bookmarks_home', | |||
|
37 | pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True) | |||
|
38 | ||||
24 | # Settings |
|
39 | # Settings | |
25 | config.add_route( |
|
40 | config.add_route( | |
26 | name='edit_repo', |
|
41 | name='edit_repo', |
@@ -18,24 +18,35 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
|
21 | import pytest | |||
21 | from rhodecode.model.db import Repository |
|
22 | from rhodecode.model.db import Repository | |
22 | from rhodecode.tests import * |
|
|||
23 |
|
23 | |||
24 |
|
24 | |||
25 | class TestBookmarksController(TestController): |
|
25 | def route_path(name, params=None, **kwargs): | |
|
26 | import urllib | |||
|
27 | ||||
|
28 | base_url = { | |||
|
29 | 'bookmarks_home': '/{repo_name}/bookmarks', | |||
|
30 | }[name].format(**kwargs) | |||
|
31 | ||||
|
32 | if params: | |||
|
33 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
34 | return base_url | |||
|
35 | ||||
|
36 | ||||
|
37 | @pytest.mark.usefixtures('autologin_user', 'app') | |||
|
38 | class TestBookmarks(object): | |||
26 |
|
39 | |||
27 | def test_index(self, backend): |
|
40 | def test_index(self, backend): | |
28 | self.log_user() |
|
|||
29 | if backend.alias == 'hg': |
|
41 | if backend.alias == 'hg': | |
30 |
response = self.app.get( |
|
42 | response = self.app.get( | |
31 | action='index', |
|
43 | route_path('bookmarks_home', repo_name=backend.repo_name)) | |
32 | repo_name=backend.repo_name)) |
|
|||
33 |
|
44 | |||
34 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
45 | repo = Repository.get_by_repo_name(backend.repo_name) | |
35 | for commit_id, obj_name in repo.scm_instance().bookmarks.items(): |
|
46 | for commit_id, obj_name in repo.scm_instance().bookmarks.items(): | |
36 | assert commit_id in response |
|
47 | assert commit_id in response | |
37 | assert obj_name in response |
|
48 | assert obj_name in response | |
38 | else: |
|
49 | else: | |
39 |
self.app.get( |
|
50 | self.app.get( | |
40 | action='index', |
|
51 | route_path('bookmarks_home', repo_name=backend.repo_name), | |
41 | repo_name=backend.repo_name), status=404) No newline at end of file |
|
52 | status=404) |
@@ -18,17 +18,28 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
|
21 | import pytest | |||
21 | from rhodecode.model.db import Repository |
|
22 | from rhodecode.model.db import Repository | |
22 | from rhodecode.tests import * |
|
|||
23 |
|
23 | |||
24 |
|
24 | |||
25 | class TestBranchesController(TestController): |
|
25 | def route_path(name, params=None, **kwargs): | |
|
26 | import urllib | |||
|
27 | ||||
|
28 | base_url = { | |||
|
29 | 'branches_home': '/{repo_name}/branches', | |||
|
30 | }[name].format(**kwargs) | |||
|
31 | ||||
|
32 | if params: | |||
|
33 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
34 | return base_url | |||
|
35 | ||||
|
36 | ||||
|
37 | @pytest.mark.usefixtures('autologin_user', 'app') | |||
|
38 | class TestBranchesController(object): | |||
26 |
|
39 | |||
27 | def test_index(self, backend): |
|
40 | def test_index(self, backend): | |
28 | self.log_user() |
|
41 | response = self.app.get( | |
29 | response = self.app.get(url(controller='branches', |
|
42 | route_path('branches_home', repo_name=backend.repo_name)) | |
30 | action='index', |
|
|||
31 | repo_name=backend.repo_name)) |
|
|||
32 |
|
43 | |||
33 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
44 | repo = Repository.get_by_repo_name(backend.repo_name) | |
34 |
|
45 |
@@ -18,16 +18,27 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
|
21 | import pytest | |||
21 | from rhodecode.model.db import Repository |
|
22 | from rhodecode.model.db import Repository | |
22 | from rhodecode.tests import * |
|
|||
23 |
|
23 | |||
24 |
|
24 | |||
25 | class TestTagsController(TestController): |
|
25 | def route_path(name, params=None, **kwargs): | |
|
26 | import urllib | |||
|
27 | ||||
|
28 | base_url = { | |||
|
29 | 'tags_home': '/{repo_name}/tags', | |||
|
30 | }[name].format(**kwargs) | |||
|
31 | ||||
|
32 | if params: | |||
|
33 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
34 | return base_url | |||
|
35 | ||||
|
36 | ||||
|
37 | @pytest.mark.usefixtures('autologin_user', 'app') | |||
|
38 | class TestTagsController(object): | |||
26 | def test_index(self, backend): |
|
39 | def test_index(self, backend): | |
27 | self.log_user() |
|
40 | response = self.app.get( | |
28 | response = self.app.get(url(controller='tags', |
|
41 | route_path('tags_home', repo_name=backend.repo_name)) | |
29 | action='index', |
|
|||
30 | repo_name=backend.repo_name)) |
|
|||
31 |
|
42 | |||
32 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
43 | repo = Repository.get_by_repo_name(backend.repo_name) | |
33 |
|
44 |
@@ -890,18 +890,6 b' def make_map(config):' | |||||
890 | controller='summary', conditions={'function': check_repo}, |
|
890 | controller='summary', conditions={'function': check_repo}, | |
891 | requirements=URL_NAME_REQUIREMENTS) |
|
891 | requirements=URL_NAME_REQUIREMENTS) | |
892 |
|
892 | |||
893 | rmap.connect('branches_home', '/{repo_name}/branches', |
|
|||
894 | controller='branches', conditions={'function': check_repo}, |
|
|||
895 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
896 |
|
||||
897 | rmap.connect('tags_home', '/{repo_name}/tags', |
|
|||
898 | controller='tags', conditions={'function': check_repo}, |
|
|||
899 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
900 |
|
||||
901 | rmap.connect('bookmarks_home', '/{repo_name}/bookmarks', |
|
|||
902 | controller='bookmarks', conditions={'function': check_repo}, |
|
|||
903 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
904 |
|
||||
905 | rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True, |
|
893 | rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True, | |
906 | controller='changelog', conditions={'function': check_repo}, |
|
894 | controller='changelog', conditions={'function': check_repo}, | |
907 | requirements=URL_NAME_REQUIREMENTS) |
|
895 | requirements=URL_NAME_REQUIREMENTS) |
@@ -96,6 +96,9 b' function registerRCRoutes() {' | |||||
96 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); |
|
96 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); | |
97 | pyroutes.register('repo_list_data', '/_repos', []); |
|
97 | pyroutes.register('repo_list_data', '/_repos', []); | |
98 | pyroutes.register('goto_switcher_data', '/_goto_data', []); |
|
98 | pyroutes.register('goto_switcher_data', '/_goto_data', []); | |
|
99 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); | |||
|
100 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); | |||
|
101 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); | |||
99 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); |
|
102 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); | |
100 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); |
|
103 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); | |
101 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); |
|
104 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); |
@@ -1,27 +1,27 b'' | |||||
1 | <%def name="refs_counters(branches, closed_branches, tags, bookmarks)"> |
|
1 | <%def name="refs_counters(branches, closed_branches, tags, bookmarks)"> | |
2 | <span class="branchtag tag"> |
|
2 | <span class="branchtag tag"> | |
3 |
<a href="${h. |
|
3 | <a href="${h.route_path('branches_home',repo_name=c.repo_name)}" class="childs"> | |
4 | <i class="icon-branch"></i>${ungettext( |
|
4 | <i class="icon-branch"></i>${ungettext( | |
5 | '%(num)s Branch','%(num)s Branches', len(branches)) % {'num': len(branches)}}</a> |
|
5 | '%(num)s Branch','%(num)s Branches', len(branches)) % {'num': len(branches)}}</a> | |
6 | </span> |
|
6 | </span> | |
7 |
|
7 | |||
8 | %if closed_branches: |
|
8 | %if closed_branches: | |
9 | <span class="branchtag tag"> |
|
9 | <span class="branchtag tag"> | |
10 |
<a href="${h. |
|
10 | <a href="${h.route_path('branches_home',repo_name=c.repo_name)}" class="childs"> | |
11 | <i class="icon-branch"></i>${ungettext( |
|
11 | <i class="icon-branch"></i>${ungettext( | |
12 | '%(num)s Closed Branch', '%(num)s Closed Branches', len(closed_branches)) % {'num': len(closed_branches)}}</a> |
|
12 | '%(num)s Closed Branch', '%(num)s Closed Branches', len(closed_branches)) % {'num': len(closed_branches)}}</a> | |
13 | </span> |
|
13 | </span> | |
14 | %endif |
|
14 | %endif | |
15 |
|
15 | |||
16 | <span class="tagtag tag"> |
|
16 | <span class="tagtag tag"> | |
17 |
<a href="${h. |
|
17 | <a href="${h.route_path('tags_home',repo_name=c.repo_name)}" class="childs"> | |
18 | <i class="icon-tag"></i>${ungettext( |
|
18 | <i class="icon-tag"></i>${ungettext( | |
19 | '%(num)s Tag', '%(num)s Tags', len(tags)) % {'num': len(tags)}}</a> |
|
19 | '%(num)s Tag', '%(num)s Tags', len(tags)) % {'num': len(tags)}}</a> | |
20 | </span> |
|
20 | </span> | |
21 |
|
21 | |||
22 | %if bookmarks: |
|
22 | %if bookmarks: | |
23 | <span class="booktag tag"> |
|
23 | <span class="booktag tag"> | |
24 |
<a href="${h. |
|
24 | <a href="${h.route_path('bookmarks_home',repo_name=c.repo_name)}" class="childs"> | |
25 | <i class="icon-bookmark"></i>${ungettext( |
|
25 | <i class="icon-bookmark"></i>${ungettext( | |
26 | '%(num)s Bookmark', '%(num)s Bookmarks', len(bookmarks)) % {'num': len(bookmarks)}}</a> |
|
26 | '%(num)s Bookmark', '%(num)s Bookmarks', len(bookmarks)) % {'num': len(bookmarks)}}</a> | |
27 | </span> |
|
27 | </span> |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now