##// END OF EJS Templates
fixed rss repo links for repos in groups
marcink -
r4098:21af6c4e default
parent child Browse files
Show More
@@ -1,178 +1,178 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.feed
3 rhodecode.controllers.feed
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Feed controller for rhodecode
6 Feed controller for rhodecode
7
7
8 :created_on: Apr 23, 2010
8 :created_on: Apr 23, 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 url, response, tmpl_context as c
28 from pylons import url, response, tmpl_context as c
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from beaker.cache import cache_region, region_invalidate
31 from beaker.cache import cache_region, region_invalidate
32 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
33
33
34 from rhodecode.lib import helpers as h
34 from rhodecode.lib import 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
36 from rhodecode.lib.base import BaseRepoController
37 from rhodecode.lib.diffs import DiffProcessor, LimitedDiffContainer
37 from rhodecode.lib.diffs import DiffProcessor, LimitedDiffContainer
38 from rhodecode.model.db import CacheInvalidation
38 from rhodecode.model.db import CacheInvalidation
39 from rhodecode.lib.utils2 import safe_int, str2bool, safe_unicode
39 from rhodecode.lib.utils2 import safe_int, str2bool, safe_unicode
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43
43
44 class FeedController(BaseRepoController):
44 class FeedController(BaseRepoController):
45
45
46 @LoginRequired(api_access=True)
46 @LoginRequired(api_access=True)
47 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
47 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
48 'repository.admin')
48 'repository.admin')
49 def __before__(self):
49 def __before__(self):
50 super(FeedController, self).__before__()
50 super(FeedController, self).__before__()
51 #common values for feeds
51 #common values for feeds
52 self.description = _('Changes on %s repository')
52 self.description = _('Changes on %s repository')
53 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
53 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
54 self.language = 'en-us'
54 self.language = 'en-us'
55 self.ttl = "5"
55 self.ttl = "5"
56 import rhodecode
56 import rhodecode
57 CONF = rhodecode.CONFIG
57 CONF = rhodecode.CONFIG
58 self.include_diff = str2bool(CONF.get('rss_include_diff', False))
58 self.include_diff = str2bool(CONF.get('rss_include_diff', False))
59 self.feed_nr = safe_int(CONF.get('rss_items_per_page', 20))
59 self.feed_nr = safe_int(CONF.get('rss_items_per_page', 20))
60 # we need to protect from parsing huge diffs here other way
60 # we need to protect from parsing huge diffs here other way
61 # we can kill the server
61 # we can kill the server
62 self.feed_diff_limit = safe_int(CONF.get('rss_cut_off_limit', 32 * 1024))
62 self.feed_diff_limit = safe_int(CONF.get('rss_cut_off_limit', 32 * 1024))
63
63
64 def _get_title(self, cs):
64 def _get_title(self, cs):
65 return "%s" % (
65 return "%s" % (
66 h.shorter(cs.message, 160)
66 h.shorter(cs.message, 160)
67 )
67 )
68
68
69 def __changes(self, cs):
69 def __changes(self, cs):
70 changes = []
70 changes = []
71 diff_processor = DiffProcessor(cs.diff(),
71 diff_processor = DiffProcessor(cs.diff(),
72 diff_limit=self.feed_diff_limit)
72 diff_limit=self.feed_diff_limit)
73 _parsed = diff_processor.prepare(inline_diff=False)
73 _parsed = diff_processor.prepare(inline_diff=False)
74 limited_diff = False
74 limited_diff = False
75 if isinstance(_parsed, LimitedDiffContainer):
75 if isinstance(_parsed, LimitedDiffContainer):
76 limited_diff = True
76 limited_diff = True
77
77
78 for st in _parsed:
78 for st in _parsed:
79 st.update({'added': st['stats']['added'],
79 st.update({'added': st['stats']['added'],
80 'removed': st['stats']['deleted']})
80 'removed': st['stats']['deleted']})
81 changes.append('\n %(operation)s %(filename)s '
81 changes.append('\n %(operation)s %(filename)s '
82 '(%(added)s lines added, %(removed)s lines removed)'
82 '(%(added)s lines added, %(removed)s lines removed)'
83 % st)
83 % st)
84 if limited_diff:
84 if limited_diff:
85 changes = changes + ['\n ' +
85 changes = changes + ['\n ' +
86 _('Changeset was too big and was cut off...')]
86 _('Changeset was too big and was cut off...')]
87 return diff_processor, changes
87 return diff_processor, changes
88
88
89 def __get_desc(self, cs):
89 def __get_desc(self, cs):
90 desc_msg = [(_('%s committed on %s')
90 desc_msg = [(_('%s committed on %s')
91 % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>']
91 % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>']
92 #branches, tags, bookmarks
92 #branches, tags, bookmarks
93 if cs.branch:
93 if cs.branch:
94 desc_msg.append('branch: %s<br/>' % cs.branch)
94 desc_msg.append('branch: %s<br/>' % cs.branch)
95 if h.is_hg(c.rhodecode_repo):
95 if h.is_hg(c.rhodecode_repo):
96 for book in cs.bookmarks:
96 for book in cs.bookmarks:
97 desc_msg.append('bookmark: %s<br/>' % book)
97 desc_msg.append('bookmark: %s<br/>' % book)
98 for tag in cs.tags:
98 for tag in cs.tags:
99 desc_msg.append('tag: %s<br/>' % tag)
99 desc_msg.append('tag: %s<br/>' % tag)
100 diff_processor, changes = self.__changes(cs)
100 diff_processor, changes = self.__changes(cs)
101 # rev link
101 # rev link
102 _url = url('changeset_home', repo_name=cs.repository.name,
102 _url = url('changeset_home', repo_name=c.rhodecode_db_repo.repo_name,
103 revision=cs.raw_id, qualified=True)
103 revision=cs.raw_id, qualified=True)
104 desc_msg.append('changeset: <a href="%s">%s</a>' % (_url, cs.raw_id[:8]))
104 desc_msg.append('changeset: <a href="%s">%s</a>' % (_url, cs.raw_id[:8]))
105
105
106 desc_msg.append('<pre>')
106 desc_msg.append('<pre>')
107 desc_msg.append(cs.message)
107 desc_msg.append(cs.message)
108 desc_msg.append('\n')
108 desc_msg.append('\n')
109 desc_msg.extend(changes)
109 desc_msg.extend(changes)
110 if self.include_diff:
110 if self.include_diff:
111 desc_msg.append('\n\n')
111 desc_msg.append('\n\n')
112 desc_msg.append(diff_processor.as_raw())
112 desc_msg.append(diff_processor.as_raw())
113 desc_msg.append('</pre>')
113 desc_msg.append('</pre>')
114 return map(safe_unicode, desc_msg)
114 return map(safe_unicode, desc_msg)
115
115
116 def atom(self, repo_name):
116 def atom(self, repo_name):
117 """Produce an atom-1.0 feed via feedgenerator module"""
117 """Produce an atom-1.0 feed via feedgenerator module"""
118
118
119 @cache_region('long_term')
119 @cache_region('long_term')
120 def _get_feed_from_cache(key, kind):
120 def _get_feed_from_cache(key, kind):
121 feed = Atom1Feed(
121 feed = Atom1Feed(
122 title=self.title % repo_name,
122 title=self.title % repo_name,
123 link=url('summary_home', repo_name=repo_name,
123 link=url('summary_home', repo_name=repo_name,
124 qualified=True),
124 qualified=True),
125 description=self.description % repo_name,
125 description=self.description % repo_name,
126 language=self.language,
126 language=self.language,
127 ttl=self.ttl
127 ttl=self.ttl
128 )
128 )
129
129
130 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
130 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
131 feed.add_item(title=self._get_title(cs),
131 feed.add_item(title=self._get_title(cs),
132 link=url('changeset_home', repo_name=repo_name,
132 link=url('changeset_home', repo_name=repo_name,
133 revision=cs.raw_id, qualified=True),
133 revision=cs.raw_id, qualified=True),
134 author_name=cs.author,
134 author_name=cs.author,
135 description=''.join(self.__get_desc(cs)),
135 description=''.join(self.__get_desc(cs)),
136 pubdate=cs.date,
136 pubdate=cs.date,
137 )
137 )
138
138
139 response.content_type = feed.mime_type
139 response.content_type = feed.mime_type
140 return feed.writeString('utf-8')
140 return feed.writeString('utf-8')
141
141
142 kind = 'ATOM'
142 kind = 'ATOM'
143 valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
143 valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
144 if not valid:
144 if not valid:
145 region_invalidate(_get_feed_from_cache, None, repo_name, kind)
145 region_invalidate(_get_feed_from_cache, None, repo_name, kind)
146 return _get_feed_from_cache(repo_name, kind)
146 return _get_feed_from_cache(repo_name, kind)
147
147
148 def rss(self, repo_name):
148 def rss(self, repo_name):
149 """Produce an rss2 feed via feedgenerator module"""
149 """Produce an rss2 feed via feedgenerator module"""
150
150
151 @cache_region('long_term')
151 @cache_region('long_term')
152 def _get_feed_from_cache(key, kind):
152 def _get_feed_from_cache(key, kind):
153 feed = Rss201rev2Feed(
153 feed = Rss201rev2Feed(
154 title=self.title % repo_name,
154 title=self.title % repo_name,
155 link=url('summary_home', repo_name=repo_name,
155 link=url('summary_home', repo_name=repo_name,
156 qualified=True),
156 qualified=True),
157 description=self.description % repo_name,
157 description=self.description % repo_name,
158 language=self.language,
158 language=self.language,
159 ttl=self.ttl
159 ttl=self.ttl
160 )
160 )
161
161
162 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
162 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
163 feed.add_item(title=self._get_title(cs),
163 feed.add_item(title=self._get_title(cs),
164 link=url('changeset_home', repo_name=repo_name,
164 link=url('changeset_home', repo_name=repo_name,
165 revision=cs.raw_id, qualified=True),
165 revision=cs.raw_id, qualified=True),
166 author_name=cs.author,
166 author_name=cs.author,
167 description=''.join(self.__get_desc(cs)),
167 description=''.join(self.__get_desc(cs)),
168 pubdate=cs.date,
168 pubdate=cs.date,
169 )
169 )
170
170
171 response.content_type = feed.mime_type
171 response.content_type = feed.mime_type
172 return feed.writeString('utf-8')
172 return feed.writeString('utf-8')
173
173
174 kind = 'RSS'
174 kind = 'RSS'
175 valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
175 valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
176 if not valid:
176 if not valid:
177 region_invalidate(_get_feed_from_cache, None, repo_name, kind)
177 region_invalidate(_get_feed_from_cache, None, repo_name, kind)
178 return _get_feed_from_cache(repo_name, kind)
178 return _get_feed_from_cache(repo_name, kind)
General Comments 0
You need to be logged in to leave comments. Login now