##// END OF EJS Templates
changelog: use unknown branch names as revisions...
Mads Kiilerich -
r4022:4a0bce84 default
parent child Browse files
Show More
@@ -1,207 +1,214 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.changelog
3 rhodecode.controllers.changelog
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 changelog controller for rhodecode
6 changelog controller for rhodecode
7
7
8 :created_on: Apr 21, 2010
8 :created_on: Apr 21, 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 import traceback
27 import traceback
28
28
29 from pylons import request, url, session, tmpl_context as c
29 from pylons import request, url, session, tmpl_context as c
30 from pylons.controllers.util import redirect
30 from pylons.controllers.util import redirect
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32 from webob.exc import HTTPNotFound, HTTPBadRequest
32 from webob.exc import HTTPNotFound, HTTPBadRequest
33
33
34 import rhodecode.lib.helpers as h
34 import rhodecode.lib.helpers as h
35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 from rhodecode.lib.base import BaseRepoController, render
36 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.helpers import RepoPage
37 from rhodecode.lib.helpers import RepoPage
38 from rhodecode.lib.compat import json
38 from rhodecode.lib.compat import json
39 from rhodecode.lib.graphmod import _colored, _dagwalker
39 from rhodecode.lib.graphmod import _colored, _dagwalker
40 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError,\
40 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError,\
41 ChangesetError, NodeDoesNotExistError, EmptyRepositoryError
41 ChangesetError, NodeDoesNotExistError, EmptyRepositoryError
42 from rhodecode.lib.utils2 import safe_int
42 from rhodecode.lib.utils2 import safe_int
43
43
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48 def _load_changelog_summary():
48 def _load_changelog_summary():
49 p = safe_int(request.GET.get('page'), 1)
49 p = safe_int(request.GET.get('page'), 1)
50 size = safe_int(request.GET.get('size'), 10)
50 size = safe_int(request.GET.get('size'), 10)
51
51
52 def url_generator(**kw):
52 def url_generator(**kw):
53 return url('changelog_summary_home',
53 return url('changelog_summary_home',
54 repo_name=c.rhodecode_db_repo.repo_name, size=size, **kw)
54 repo_name=c.rhodecode_db_repo.repo_name, size=size, **kw)
55
55
56 collection = c.rhodecode_repo
56 collection = c.rhodecode_repo
57
57
58 c.repo_changesets = RepoPage(collection, page=p,
58 c.repo_changesets = RepoPage(collection, page=p,
59 items_per_page=size,
59 items_per_page=size,
60 url=url_generator)
60 url=url_generator)
61 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
61 page_revisions = [x.raw_id for x in list(c.repo_changesets)]
62 c.comments = c.rhodecode_db_repo.get_comments(page_revisions)
62 c.comments = c.rhodecode_db_repo.get_comments(page_revisions)
63 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
63 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
64
64
65
65
66 class ChangelogController(BaseRepoController):
66 class ChangelogController(BaseRepoController):
67
67
68 def __before__(self):
68 def __before__(self):
69 super(ChangelogController, self).__before__()
69 super(ChangelogController, self).__before__()
70 c.affected_files_cut_off = 60
70 c.affected_files_cut_off = 60
71
71
72 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
72 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
73 partial=False):
73 partial=False):
74 """
74 """
75 Safe way to get changeset if error occur it redirects to changeset with
75 Safe way to get changeset if error occur it redirects to changeset with
76 proper message. If partial is set then don't do redirect raise Exception
76 proper message. If partial is set then don't do redirect raise Exception
77 instead
77 instead
78
78
79 :param rev: revision to fetch
79 :param rev: revision to fetch
80 :param repo: repo instance
80 :param repo: repo instance
81 """
81 """
82
82
83 try:
83 try:
84 return c.rhodecode_repo.get_changeset(rev)
84 return c.rhodecode_repo.get_changeset(rev)
85 except EmptyRepositoryError, e:
85 except EmptyRepositoryError, e:
86 if not redirect_after:
86 if not redirect_after:
87 return None
87 return None
88 h.flash(h.literal(_('There are no changesets yet')),
88 h.flash(h.literal(_('There are no changesets yet')),
89 category='warning')
89 category='warning')
90 redirect(url('changelog_home', repo_name=repo.repo_name))
90 redirect(url('changelog_home', repo_name=repo.repo_name))
91
91
92 except RepositoryError, e:
92 except RepositoryError, e:
93 log.error(traceback.format_exc())
93 log.error(traceback.format_exc())
94 h.flash(str(e), category='warning')
94 h.flash(str(e), category='warning')
95 if not partial:
95 if not partial:
96 redirect(h.url('changelog_home', repo_name=repo.repo_name))
96 redirect(h.url('changelog_home', repo_name=repo.repo_name))
97 raise HTTPBadRequest()
97 raise HTTPBadRequest()
98
98
99 def _graph(self, repo, revs_int, repo_size, size, p):
99 def _graph(self, repo, revs_int, repo_size, size, p):
100 """
100 """
101 Generates a DAG graph for repo
101 Generates a DAG graph for repo
102
102
103 :param repo:
103 :param repo:
104 :param revs_int:
104 :param revs_int:
105 :param repo_size:
105 :param repo_size:
106 :param size:
106 :param size:
107 :param p:
107 :param p:
108 """
108 """
109 if not revs_int:
109 if not revs_int:
110 c.jsdata = json.dumps([])
110 c.jsdata = json.dumps([])
111 return
111 return
112
112
113 data = []
113 data = []
114 revs = revs_int
114 revs = revs_int
115
115
116 dag = _dagwalker(repo, revs, repo.alias)
116 dag = _dagwalker(repo, revs, repo.alias)
117 dag = _colored(dag)
117 dag = _colored(dag)
118 for (id, type, ctx, vtx, edges) in dag:
118 for (id, type, ctx, vtx, edges) in dag:
119 data.append(['', vtx, edges])
119 data.append(['', vtx, edges])
120
120
121 c.jsdata = json.dumps(data)
121 c.jsdata = json.dumps(data)
122
122
123 @LoginRequired()
123 @LoginRequired()
124 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
124 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
125 'repository.admin')
125 'repository.admin')
126 def index(self, repo_name, revision=None, f_path=None):
126 def index(self, repo_name, revision=None, f_path=None):
127 limit = 100
127 limit = 100
128 default = 20
128 default = 20
129 if request.GET.get('size'):
129 if request.GET.get('size'):
130 c.size = max(min(safe_int(request.GET.get('size')), limit), 1)
130 c.size = max(min(safe_int(request.GET.get('size')), limit), 1)
131 session['changelog_size'] = c.size
131 session['changelog_size'] = c.size
132 session.save()
132 session.save()
133 else:
133 else:
134 c.size = int(session.get('changelog_size', default))
134 c.size = int(session.get('changelog_size', default))
135 # min size must be 1
135 # min size must be 1
136 c.size = max(c.size, 1)
136 c.size = max(c.size, 1)
137 p = safe_int(request.GET.get('page', 1), 1)
137 p = safe_int(request.GET.get('page', 1), 1)
138 branch_name = request.GET.get('branch', None)
138 branch_name = request.GET.get('branch', None)
139 if (branch_name and
140 branch_name not in c.rhodecode_repo.branches and
141 branch_name not in c.rhodecode_repo.closed_branches and
142 not revision):
143 return redirect(url('changelog_file_home', repo_name=c.repo_name,
144 revision=branch_name, f_path=f_path or ''))
145
139 c.changelog_for_path = f_path
146 c.changelog_for_path = f_path
140 try:
147 try:
141
148
142 if f_path:
149 if f_path:
143 log.debug('generating changelog for path %s' % f_path)
150 log.debug('generating changelog for path %s' % f_path)
144 # get the history for the file !
151 # get the history for the file !
145 tip_cs = c.rhodecode_repo.get_changeset()
152 tip_cs = c.rhodecode_repo.get_changeset()
146 try:
153 try:
147 collection = tip_cs.get_file_history(f_path)
154 collection = tip_cs.get_file_history(f_path)
148 except (NodeDoesNotExistError, ChangesetError):
155 except (NodeDoesNotExistError, ChangesetError):
149 #this node is not present at tip !
156 #this node is not present at tip !
150 try:
157 try:
151 cs = self.__get_css_or_redirect(revision, repo_name)
158 cs = self.__get_css_or_redirect(revision, repo_name)
152 collection = cs.get_file_history(f_path)
159 collection = cs.get_file_history(f_path)
153 except RepositoryError, e:
160 except RepositoryError, e:
154 h.flash(str(e), category='warning')
161 h.flash(str(e), category='warning')
155 redirect(h.url('changelog_home', repo_name=repo_name))
162 redirect(h.url('changelog_home', repo_name=repo_name))
156 collection = list(reversed(collection))
163 collection = list(reversed(collection))
157 else:
164 else:
158 collection = c.rhodecode_repo.get_changesets(start=0,
165 collection = c.rhodecode_repo.get_changesets(start=0,
159 branch_name=branch_name)
166 branch_name=branch_name)
160 c.total_cs = len(collection)
167 c.total_cs = len(collection)
161
168
162 c.pagination = RepoPage(collection, page=p, item_count=c.total_cs,
169 c.pagination = RepoPage(collection, page=p, item_count=c.total_cs,
163 items_per_page=c.size, branch=branch_name,)
170 items_per_page=c.size, branch=branch_name,)
164 collection = list(c.pagination)
171 collection = list(c.pagination)
165 page_revisions = [x.raw_id for x in c.pagination]
172 page_revisions = [x.raw_id for x in c.pagination]
166 c.comments = c.rhodecode_db_repo.get_comments(page_revisions)
173 c.comments = c.rhodecode_db_repo.get_comments(page_revisions)
167 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
174 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
168 except (EmptyRepositoryError), e:
175 except (EmptyRepositoryError), e:
169 h.flash(str(e), category='warning')
176 h.flash(str(e), category='warning')
170 return redirect(url('summary_home', repo_name=c.repo_name))
177 return redirect(url('summary_home', repo_name=c.repo_name))
171 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
178 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
172 log.error(traceback.format_exc())
179 log.error(traceback.format_exc())
173 h.flash(str(e), category='error')
180 h.flash(str(e), category='error')
174 return redirect(url('changelog_home', repo_name=c.repo_name))
181 return redirect(url('changelog_home', repo_name=c.repo_name))
175
182
176 c.branch_name = branch_name
183 c.branch_name = branch_name
177 c.branch_filters = [('', _('All Branches'))] + \
184 c.branch_filters = [('', _('All Branches'))] + \
178 [(k, k) for k in c.rhodecode_repo.branches.keys()]
185 [(k, k) for k in c.rhodecode_repo.branches.keys()]
179 if c.rhodecode_repo.closed_branches:
186 if c.rhodecode_repo.closed_branches:
180 prefix = _('(closed)') + ' '
187 prefix = _('(closed)') + ' '
181 c.branch_filters += [('-', '-')] + \
188 c.branch_filters += [('-', '-')] + \
182 [(k, prefix + k) for k in c.rhodecode_repo.closed_branches.keys()]
189 [(k, prefix + k) for k in c.rhodecode_repo.closed_branches.keys()]
183 _revs = []
190 _revs = []
184 if not f_path:
191 if not f_path:
185 _revs = [x.revision for x in c.pagination]
192 _revs = [x.revision for x in c.pagination]
186 self._graph(c.rhodecode_repo, _revs, c.total_cs, c.size, p)
193 self._graph(c.rhodecode_repo, _revs, c.total_cs, c.size, p)
187
194
188 return render('changelog/changelog.html')
195 return render('changelog/changelog.html')
189
196
190 @LoginRequired()
197 @LoginRequired()
191 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
198 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
192 'repository.admin')
199 'repository.admin')
193 def changelog_details(self, cs):
200 def changelog_details(self, cs):
194 if request.environ.get('HTTP_X_PARTIAL_XHR'):
201 if request.environ.get('HTTP_X_PARTIAL_XHR'):
195 c.cs = c.rhodecode_repo.get_changeset(cs)
202 c.cs = c.rhodecode_repo.get_changeset(cs)
196 return render('changelog/changelog_details.html')
203 return render('changelog/changelog_details.html')
197 raise HTTPNotFound()
204 raise HTTPNotFound()
198
205
199 @LoginRequired()
206 @LoginRequired()
200 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
207 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
201 'repository.admin')
208 'repository.admin')
202 def changelog_summary(self, repo_name):
209 def changelog_summary(self, repo_name):
203 if request.environ.get('HTTP_X_PARTIAL_XHR'):
210 if request.environ.get('HTTP_X_PARTIAL_XHR'):
204 _load_changelog_summary()
211 _load_changelog_summary()
205
212
206 return render('changelog/changelog_summary_data.html')
213 return render('changelog/changelog_summary_data.html')
207 raise HTTPNotFound()
214 raise HTTPNotFound()
General Comments 0
You need to be logged in to leave comments. Login now