##// END OF EJS Templates
#574 Show pull request status also in shortlog (if any)
marcink -
r2884:a16f9a76 beta
parent child Browse files
Show More
@@ -1,64 +1,66
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.shortlog
3 rhodecode.controllers.shortlog
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Shortlog controller for rhodecode
6 Shortlog controller for rhodecode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27
27
28 from pylons import tmpl_context as c, request, url
28 from pylons import tmpl_context as c, request, url
29
29
30 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
30 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
31 from rhodecode.lib.base import BaseRepoController, render
31 from rhodecode.lib.base import BaseRepoController, render
32 from rhodecode.lib.helpers import RepoPage
32 from rhodecode.lib.helpers import RepoPage
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from rhodecode.lib.utils2 import safe_int
34 from rhodecode.lib.utils2 import safe_int
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38
38
39 class ShortlogController(BaseRepoController):
39 class ShortlogController(BaseRepoController):
40
40
41 @LoginRequired()
41 @LoginRequired()
42 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
42 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
43 'repository.admin')
43 'repository.admin')
44 def __before__(self):
44 def __before__(self):
45 super(ShortlogController, self).__before__()
45 super(ShortlogController, self).__before__()
46
46
47 def index(self, repo_name):
47 def index(self, repo_name):
48 p = safe_int(request.params.get('page', 1), 1)
48 p = safe_int(request.params.get('page', 1), 1)
49 size = safe_int(request.params.get('size', 20), 20)
49 size = safe_int(request.params.get('size', 20), 20)
50
50
51 def url_generator(**kw):
51 def url_generator(**kw):
52 return url('shortlog_home', repo_name=repo_name, size=size, **kw)
52 return url('shortlog_home', repo_name=repo_name, size=size, **kw)
53
53
54 c.repo_changesets = RepoPage(c.rhodecode_repo, page=p,
54 c.repo_changesets = RepoPage(c.rhodecode_repo, page=p,
55 items_per_page=size, url=url_generator)
55 items_per_page=size, url=url_generator)
56 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
57 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
56
58
57 if not c.repo_changesets:
59 if not c.repo_changesets:
58 return redirect(url('summary_home', repo_name=repo_name))
60 return redirect(url('summary_home', repo_name=repo_name))
59
61
60 c.shortlog_data = render('shortlog/shortlog_data.html')
62 c.shortlog_data = render('shortlog/shortlog_data.html')
61 if request.environ.get('HTTP_X_PARTIAL_XHR'):
63 if request.environ.get('HTTP_X_PARTIAL_XHR'):
62 return c.shortlog_data
64 return c.shortlog_data
63 r = render('shortlog/shortlog.html')
65 r = render('shortlog/shortlog.html')
64 return r
66 return r
@@ -1,247 +1,249
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.summary
3 rhodecode.controllers.summary
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Summary controller for Rhodecode
6 Summary controller for Rhodecode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import traceback
26 import traceback
27 import calendar
27 import calendar
28 import logging
28 import logging
29 import urllib
29 import urllib
30 from time import mktime
30 from time import mktime
31 from datetime import timedelta, date
31 from datetime import timedelta, date
32 from urlparse import urlparse
32 from urlparse import urlparse
33 from rhodecode.lib.compat import product
33 from rhodecode.lib.compat import product
34
34
35 from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \
35 from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \
36 NodeDoesNotExistError
36 NodeDoesNotExistError
37
37
38 from pylons import tmpl_context as c, request, url, config
38 from pylons import tmpl_context as c, request, url, config
39 from pylons.i18n.translation import _
39 from pylons.i18n.translation import _
40
40
41 from beaker.cache import cache_region, region_invalidate
41 from beaker.cache import cache_region, region_invalidate
42
42
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
44 from rhodecode.model.db import Statistics, CacheInvalidation
44 from rhodecode.model.db import Statistics, CacheInvalidation
45 from rhodecode.lib.utils2 import safe_unicode
45 from rhodecode.lib.utils2 import safe_unicode
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
47 from rhodecode.lib.base import BaseRepoController, render
47 from rhodecode.lib.base import BaseRepoController, render
48 from rhodecode.lib.vcs.backends.base import EmptyChangeset
48 from rhodecode.lib.vcs.backends.base import EmptyChangeset
49 from rhodecode.lib.markup_renderer import MarkupRenderer
49 from rhodecode.lib.markup_renderer import MarkupRenderer
50 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib import run_task
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
52 from rhodecode.lib.helpers import RepoPage
52 from rhodecode.lib.helpers import RepoPage
53 from rhodecode.lib.compat import json, OrderedDict
53 from rhodecode.lib.compat import json, OrderedDict
54 from rhodecode.lib.vcs.nodes import FileNode
54 from rhodecode.lib.vcs.nodes import FileNode
55
55
56 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
57
57
58 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
58 README_FILES = [''.join([x[0][0], x[1][0]]) for x in
59 sorted(list(product(ALL_READMES, ALL_EXTS)),
59 sorted(list(product(ALL_READMES, ALL_EXTS)),
60 key=lambda y:y[0][1] + y[1][1])]
60 key=lambda y:y[0][1] + y[1][1])]
61
61
62
62
63 class SummaryController(BaseRepoController):
63 class SummaryController(BaseRepoController):
64
64
65 @LoginRequired()
65 @LoginRequired()
66 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
66 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
67 'repository.admin')
67 'repository.admin')
68 def __before__(self):
68 def __before__(self):
69 super(SummaryController, self).__before__()
69 super(SummaryController, self).__before__()
70
70
71 def index(self, repo_name):
71 def index(self, repo_name):
72 c.dbrepo = dbrepo = c.rhodecode_db_repo
72 c.dbrepo = dbrepo = c.rhodecode_db_repo
73 c.following = self.scm_model.is_following_repo(repo_name,
73 c.following = self.scm_model.is_following_repo(repo_name,
74 self.rhodecode_user.user_id)
74 self.rhodecode_user.user_id)
75
75
76 def url_generator(**kw):
76 def url_generator(**kw):
77 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
77 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
78
78
79 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
79 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
80 items_per_page=10, url=url_generator)
80 items_per_page=10, url=url_generator)
81 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
82 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
81
83
82 if self.rhodecode_user.username == 'default':
84 if self.rhodecode_user.username == 'default':
83 # for default(anonymous) user we don't need to pass credentials
85 # for default(anonymous) user we don't need to pass credentials
84 username = ''
86 username = ''
85 password = ''
87 password = ''
86 else:
88 else:
87 username = str(self.rhodecode_user.username)
89 username = str(self.rhodecode_user.username)
88 password = '@'
90 password = '@'
89
91
90 parsed_url = urlparse(url.current(qualified=True))
92 parsed_url = urlparse(url.current(qualified=True))
91
93
92 default_clone_uri = '{scheme}://{user}{pass}{netloc}{path}'
94 default_clone_uri = '{scheme}://{user}{pass}{netloc}{path}'
93
95
94 uri_tmpl = config.get('clone_uri', default_clone_uri)
96 uri_tmpl = config.get('clone_uri', default_clone_uri)
95 uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s')
97 uri_tmpl = uri_tmpl.replace('{', '%(').replace('}', ')s')
96 decoded_path = safe_unicode(urllib.unquote(parsed_url.path))
98 decoded_path = safe_unicode(urllib.unquote(parsed_url.path))
97 uri_dict = {
99 uri_dict = {
98 'user': username,
100 'user': username,
99 'pass': password,
101 'pass': password,
100 'scheme': parsed_url.scheme,
102 'scheme': parsed_url.scheme,
101 'netloc': parsed_url.netloc,
103 'netloc': parsed_url.netloc,
102 'path': decoded_path
104 'path': decoded_path
103 }
105 }
104
106
105 uri = uri_tmpl % uri_dict
107 uri = uri_tmpl % uri_dict
106 # generate another clone url by id
108 # generate another clone url by id
107 uri_dict.update(
109 uri_dict.update(
108 {'path': decoded_path.replace(repo_name, '_%s' % c.dbrepo.repo_id)}
110 {'path': decoded_path.replace(repo_name, '_%s' % c.dbrepo.repo_id)}
109 )
111 )
110 uri_id = uri_tmpl % uri_dict
112 uri_id = uri_tmpl % uri_dict
111
113
112 c.clone_repo_url = uri
114 c.clone_repo_url = uri
113 c.clone_repo_url_id = uri_id
115 c.clone_repo_url_id = uri_id
114 c.repo_tags = OrderedDict()
116 c.repo_tags = OrderedDict()
115 for name, hash_ in c.rhodecode_repo.tags.items()[:10]:
117 for name, hash_ in c.rhodecode_repo.tags.items()[:10]:
116 try:
118 try:
117 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash_)
119 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash_)
118 except ChangesetError:
120 except ChangesetError:
119 c.repo_tags[name] = EmptyChangeset(hash_)
121 c.repo_tags[name] = EmptyChangeset(hash_)
120
122
121 c.repo_branches = OrderedDict()
123 c.repo_branches = OrderedDict()
122 for name, hash_ in c.rhodecode_repo.branches.items()[:10]:
124 for name, hash_ in c.rhodecode_repo.branches.items()[:10]:
123 try:
125 try:
124 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash_)
126 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash_)
125 except ChangesetError:
127 except ChangesetError:
126 c.repo_branches[name] = EmptyChangeset(hash_)
128 c.repo_branches[name] = EmptyChangeset(hash_)
127
129
128 td = date.today() + timedelta(days=1)
130 td = date.today() + timedelta(days=1)
129 td_1m = td - timedelta(days=calendar.mdays[td.month])
131 td_1m = td - timedelta(days=calendar.mdays[td.month])
130 td_1y = td - timedelta(days=365)
132 td_1y = td - timedelta(days=365)
131
133
132 ts_min_m = mktime(td_1m.timetuple())
134 ts_min_m = mktime(td_1m.timetuple())
133 ts_min_y = mktime(td_1y.timetuple())
135 ts_min_y = mktime(td_1y.timetuple())
134 ts_max_y = mktime(td.timetuple())
136 ts_max_y = mktime(td.timetuple())
135
137
136 if dbrepo.enable_statistics:
138 if dbrepo.enable_statistics:
137 c.show_stats = True
139 c.show_stats = True
138 c.no_data_msg = _('No data loaded yet')
140 c.no_data_msg = _('No data loaded yet')
139 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
141 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
140 else:
142 else:
141 c.show_stats = False
143 c.show_stats = False
142 c.no_data_msg = _('Statistics are disabled for this repository')
144 c.no_data_msg = _('Statistics are disabled for this repository')
143 c.ts_min = ts_min_m
145 c.ts_min = ts_min_m
144 c.ts_max = ts_max_y
146 c.ts_max = ts_max_y
145
147
146 stats = self.sa.query(Statistics)\
148 stats = self.sa.query(Statistics)\
147 .filter(Statistics.repository == dbrepo)\
149 .filter(Statistics.repository == dbrepo)\
148 .scalar()
150 .scalar()
149
151
150 c.stats_percentage = 0
152 c.stats_percentage = 0
151
153
152 if stats and stats.languages:
154 if stats and stats.languages:
153 c.no_data = False is dbrepo.enable_statistics
155 c.no_data = False is dbrepo.enable_statistics
154 lang_stats_d = json.loads(stats.languages)
156 lang_stats_d = json.loads(stats.languages)
155 c.commit_data = stats.commit_activity
157 c.commit_data = stats.commit_activity
156 c.overview_data = stats.commit_activity_combined
158 c.overview_data = stats.commit_activity_combined
157
159
158 lang_stats = ((x, {"count": y,
160 lang_stats = ((x, {"count": y,
159 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
161 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
160 for x, y in lang_stats_d.items())
162 for x, y in lang_stats_d.items())
161
163
162 c.trending_languages = json.dumps(
164 c.trending_languages = json.dumps(
163 sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
165 sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
164 )
166 )
165 last_rev = stats.stat_on_revision + 1
167 last_rev = stats.stat_on_revision + 1
166 c.repo_last_rev = c.rhodecode_repo.count()\
168 c.repo_last_rev = c.rhodecode_repo.count()\
167 if c.rhodecode_repo.revisions else 0
169 if c.rhodecode_repo.revisions else 0
168 if last_rev == 0 or c.repo_last_rev == 0:
170 if last_rev == 0 or c.repo_last_rev == 0:
169 pass
171 pass
170 else:
172 else:
171 c.stats_percentage = '%.2f' % ((float((last_rev)) /
173 c.stats_percentage = '%.2f' % ((float((last_rev)) /
172 c.repo_last_rev) * 100)
174 c.repo_last_rev) * 100)
173 else:
175 else:
174 c.commit_data = json.dumps({})
176 c.commit_data = json.dumps({})
175 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
177 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
176 c.trending_languages = json.dumps({})
178 c.trending_languages = json.dumps({})
177 c.no_data = True
179 c.no_data = True
178
180
179 c.enable_downloads = dbrepo.enable_downloads
181 c.enable_downloads = dbrepo.enable_downloads
180 if c.enable_downloads:
182 if c.enable_downloads:
181 c.download_options = self._get_download_links(c.rhodecode_repo)
183 c.download_options = self._get_download_links(c.rhodecode_repo)
182
184
183 c.readme_data, c.readme_file = \
185 c.readme_data, c.readme_file = \
184 self.__get_readme_data(c.rhodecode_db_repo)
186 self.__get_readme_data(c.rhodecode_db_repo)
185 return render('summary/summary.html')
187 return render('summary/summary.html')
186
188
187 def __get_readme_data(self, db_repo):
189 def __get_readme_data(self, db_repo):
188 repo_name = db_repo.repo_name
190 repo_name = db_repo.repo_name
189
191
190 @cache_region('long_term')
192 @cache_region('long_term')
191 def _get_readme_from_cache(key):
193 def _get_readme_from_cache(key):
192 readme_data = None
194 readme_data = None
193 readme_file = None
195 readme_file = None
194 log.debug('Looking for README file')
196 log.debug('Looking for README file')
195 try:
197 try:
196 # get's the landing revision! or tip if fails
198 # get's the landing revision! or tip if fails
197 cs = db_repo.get_landing_changeset()
199 cs = db_repo.get_landing_changeset()
198 if isinstance(cs, EmptyChangeset):
200 if isinstance(cs, EmptyChangeset):
199 raise EmptyRepositoryError()
201 raise EmptyRepositoryError()
200 renderer = MarkupRenderer()
202 renderer = MarkupRenderer()
201 for f in README_FILES:
203 for f in README_FILES:
202 try:
204 try:
203 readme = cs.get_node(f)
205 readme = cs.get_node(f)
204 if not isinstance(readme, FileNode):
206 if not isinstance(readme, FileNode):
205 continue
207 continue
206 readme_file = f
208 readme_file = f
207 log.debug('Found README file `%s` rendering...' %
209 log.debug('Found README file `%s` rendering...' %
208 readme_file)
210 readme_file)
209 readme_data = renderer.render(readme.content, f)
211 readme_data = renderer.render(readme.content, f)
210 break
212 break
211 except NodeDoesNotExistError:
213 except NodeDoesNotExistError:
212 continue
214 continue
213 except ChangesetError:
215 except ChangesetError:
214 log.error(traceback.format_exc())
216 log.error(traceback.format_exc())
215 pass
217 pass
216 except EmptyRepositoryError:
218 except EmptyRepositoryError:
217 pass
219 pass
218 except Exception:
220 except Exception:
219 log.error(traceback.format_exc())
221 log.error(traceback.format_exc())
220
222
221 return readme_data, readme_file
223 return readme_data, readme_file
222
224
223 key = repo_name + '_README'
225 key = repo_name + '_README'
224 inv = CacheInvalidation.invalidate(key)
226 inv = CacheInvalidation.invalidate(key)
225 if inv is not None:
227 if inv is not None:
226 region_invalidate(_get_readme_from_cache, None, key)
228 region_invalidate(_get_readme_from_cache, None, key)
227 CacheInvalidation.set_valid(inv.cache_key)
229 CacheInvalidation.set_valid(inv.cache_key)
228 return _get_readme_from_cache(key)
230 return _get_readme_from_cache(key)
229
231
230 def _get_download_links(self, repo):
232 def _get_download_links(self, repo):
231
233
232 download_l = []
234 download_l = []
233
235
234 branches_group = ([], _("Branches"))
236 branches_group = ([], _("Branches"))
235 tags_group = ([], _("Tags"))
237 tags_group = ([], _("Tags"))
236
238
237 for name, chs in c.rhodecode_repo.branches.items():
239 for name, chs in c.rhodecode_repo.branches.items():
238 #chs = chs.split(':')[-1]
240 #chs = chs.split(':')[-1]
239 branches_group[0].append((chs, name),)
241 branches_group[0].append((chs, name),)
240 download_l.append(branches_group)
242 download_l.append(branches_group)
241
243
242 for name, chs in c.rhodecode_repo.tags.items():
244 for name, chs in c.rhodecode_repo.tags.items():
243 #chs = chs.split(':')[-1]
245 #chs = chs.split(':')[-1]
244 tags_group[0].append((chs, name),)
246 tags_group[0].append((chs, name),)
245 download_l.append(tags_group)
247 download_l.append(tags_group)
246
248
247 return download_l
249 return download_l
@@ -1,88 +1,103
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 %if c.repo_changesets:
2 %if c.repo_changesets:
3 <table class="table_disp">
3 <table class="table_disp">
4 <tr>
4 <tr>
5 <th class="left">${_('revision')}</th>
5 <th class="left">${_('revision')}</th>
6 <th class="left">${_('commit message')}</th>
6 <th class="left">${_('commit message')}</th>
7 <th class="left">${_('age')}</th>
7 <th class="left">${_('age')}</th>
8 <th class="left">${_('author')}</th>
8 <th class="left">${_('author')}</th>
9 <th class="left">${_('branch')}</th>
9 <th class="left">${_('branch')}</th>
10 <th class="left">${_('tags')}</th>
10 <th class="left">${_('tags')}</th>
11 </tr>
11 </tr>
12 %for cnt,cs in enumerate(c.repo_changesets):
12 %for cnt,cs in enumerate(c.repo_changesets):
13 <tr class="parity${cnt%2}">
13 <tr class="parity${cnt%2}">
14 <td>
14 <td>
15 <div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div>
15 <div>
16 <div class="changeset-status-container">
17 %if c.statuses.get(cs.raw_id):
18 <div class="changeset-status-ico">
19 %if c.statuses.get(cs.raw_id)[2]:
20 <a class="tooltip" title="${_('Click to open associated pull request')}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
21 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
22 </a>
23 %else:
24 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
25 %endif
26 </div>
27 %endif
28 </div>
29 <pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre>
30 </div>
16 </td>
31 </td>
17 <td>
32 <td>
18 ${h.link_to(h.truncate(cs.message,50) or _('No commit message'),
33 ${h.link_to(h.truncate(cs.message,50) or _('No commit message'),
19 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
34 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
20 title=cs.message)}
35 title=cs.message)}
21 </td>
36 </td>
22 <td><span class="tooltip" title="${h.tooltip(h.fmt_date(cs.date))}">
37 <td><span class="tooltip" title="${h.tooltip(h.fmt_date(cs.date))}">
23 ${h.age(cs.date)}</span>
38 ${h.age(cs.date)}</span>
24 </td>
39 </td>
25 <td title="${cs.author}">${h.person(cs.author)}</td>
40 <td title="${cs.author}">${h.person(cs.author)}</td>
26 <td>
41 <td>
27 <span class="logtags">
42 <span class="logtags">
28 %if cs.branch:
43 %if cs.branch:
29 <span class="branchtag">
44 <span class="branchtag">
30 ${cs.branch}
45 ${cs.branch}
31 </span>
46 </span>
32 %endif
47 %endif
33 </span>
48 </span>
34 </td>
49 </td>
35 <td>
50 <td>
36 <span class="logtags">
51 <span class="logtags">
37 %for tag in cs.tags:
52 %for tag in cs.tags:
38 <span class="tagtag">${tag}</span>
53 <span class="tagtag">${tag}</span>
39 %endfor
54 %endfor
40 </span>
55 </span>
41 </td>
56 </td>
42 </tr>
57 </tr>
43 %endfor
58 %endfor
44
59
45 </table>
60 </table>
46
61
47 <script type="text/javascript">
62 <script type="text/javascript">
48 YUE.onDOMReady(function(){
63 YUE.onDOMReady(function(){
49 YUE.delegate("shortlog_data","click",function(e, matchedEl, container){
64 YUE.delegate("shortlog_data","click",function(e, matchedEl, container){
50 ypjax(e.target.href,"shortlog_data",function(){tooltip_activate();});
65 ypjax(e.target.href,"shortlog_data",function(){tooltip_activate();});
51 YUE.preventDefault(e);
66 YUE.preventDefault(e);
52 },'.pager_link');
67 },'.pager_link');
53 });
68 });
54 </script>
69 </script>
55
70
56 <div class="pagination-wh pagination-left">
71 <div class="pagination-wh pagination-left">
57 ${c.repo_changesets.pager('$link_previous ~2~ $link_next')}
72 ${c.repo_changesets.pager('$link_previous ~2~ $link_next')}
58 </div>
73 </div>
59 %else:
74 %else:
60
75
61 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
76 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
62 <h4>${_('Add or upload files directly via RhodeCode')}</h4>
77 <h4>${_('Add or upload files directly via RhodeCode')}</h4>
63 <div style="margin: 20px 30px;">
78 <div style="margin: 20px 30px;">
64 <div id="add_node_id" class="add_node">
79 <div id="add_node_id" class="add_node">
65 <a class="ui-btn" href="${h.url('files_add_home',repo_name=c.repo_name,revision=0,f_path='')}">${_('add new file')}</a>
80 <a class="ui-btn" href="${h.url('files_add_home',repo_name=c.repo_name,revision=0,f_path='')}">${_('add new file')}</a>
66 </div>
81 </div>
67 </div>
82 </div>
68 %endif
83 %endif
69
84
70
85
71 <h4>${_('Push new repo')}</h4>
86 <h4>${_('Push new repo')}</h4>
72 <pre>
87 <pre>
73 ${c.rhodecode_repo.alias} clone ${c.clone_repo_url}
88 ${c.rhodecode_repo.alias} clone ${c.clone_repo_url}
74 ${c.rhodecode_repo.alias} add README # add first file
89 ${c.rhodecode_repo.alias} add README # add first file
75 ${c.rhodecode_repo.alias} commit -m "Initial" # commit with message
90 ${c.rhodecode_repo.alias} commit -m "Initial" # commit with message
76 ${c.rhodecode_repo.alias} push ${'origin master' if h.is_git(c.rhodecode_repo) else ''} # push changes back
91 ${c.rhodecode_repo.alias} push ${'origin master' if h.is_git(c.rhodecode_repo) else ''} # push changes back
77 </pre>
92 </pre>
78
93
79 <h4>${_('Existing repository?')}</h4>
94 <h4>${_('Existing repository?')}</h4>
80 <pre>
95 <pre>
81 %if h.is_git(c.rhodecode_repo):
96 %if h.is_git(c.rhodecode_repo):
82 git remote add origin ${c.clone_repo_url}
97 git remote add origin ${c.clone_repo_url}
83 git push -u origin master
98 git push -u origin master
84 %else:
99 %else:
85 hg push ${c.clone_repo_url}
100 hg push ${c.clone_repo_url}
86 %endif
101 %endif
87 </pre>
102 </pre>
88 %endif
103 %endif
General Comments 0
You need to be logged in to leave comments. Login now