##// END OF EJS Templates
Improved RSS/ATOM feeds...
marcink -
r2385:a455b2c7 beta
parent child Browse files
Show More
@@ -544,6 +544,15 b' class ApiController(JSONRPCController):'
544 544 raise JSONRPCError('failed to create repository %s' % repo_name)
545 545
546 546 @HasPermissionAnyDecorator('hg.admin')
547 def fork_repo(self, apiuser, repoid):
548 repo = RepoModel().get_repo(repoid)
549 if repo is None:
550 raise JSONRPCError('unknown repository "%s"' % (repo or repoid))
551
552 RepoModel().create_fork(form_data, cur_user)
553
554
555 @HasPermissionAnyDecorator('hg.admin')
547 556 def delete_repo(self, apiuser, repo_name):
548 557 """
549 558 Deletes a given repository
@@ -28,11 +28,12 b' import logging'
28 28 from pylons import url, response, tmpl_context as c
29 29 from pylons.i18n.translation import _
30 30
31 from rhodecode.lib.utils2 import safe_unicode
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32
33 from rhodecode.lib import helpers as h
32 34 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 35 from rhodecode.lib.base import BaseRepoController
34
35 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
36 from rhodecode.lib.diffs import DiffProcessor
36 37
37 38 log = logging.getLogger(__name__)
38 39
@@ -49,31 +50,36 b' class FeedController(BaseRepoController)'
49 50 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
50 51 self.language = 'en-us'
51 52 self.ttl = "5"
52 self.feed_nr = 10
53 self.feed_nr = 20
53 54
54 55 def _get_title(self, cs):
55 return "R%s:%s - %s" % (
56 cs.revision, cs.short_id, cs.message
56 return "%s" % (
57 h.shorter(cs.message, 160)
57 58 )
58 59
59 60 def __changes(self, cs):
60 61 changes = []
61 62
62 a = [safe_unicode(n.path) for n in cs.added]
63 if a:
64 changes.append('\nA ' + '\nA '.join(a))
65
66 m = [safe_unicode(n.path) for n in cs.changed]
67 if m:
68 changes.append('\nM ' + '\nM '.join(m))
63 diffprocessor = DiffProcessor(cs.diff())
64 stats = diffprocessor.prepare(inline_diff=False)
65 for st in stats:
66 st.update({'added': st['stats'][0],
67 'removed': st['stats'][1]})
68 changes.append('\n %(operation)s %(filename)s '
69 '(%(added)s lines added, %(removed)s lines removed)'
70 % st)
71 return changes
69 72
70 d = [safe_unicode(n.path) for n in cs.removed]
71 if d:
72 changes.append('\nD ' + '\nD '.join(d))
73
74 changes.append('</pre>')
75
76 return ''.join(changes)
73 def __get_desc(self, cs):
74 desc_msg = []
75 desc_msg.append('%s %s %s:<br/>' % (cs.author, _('commited on'),
76 cs.date))
77 desc_msg.append('<pre>')
78 desc_msg.append(cs.message)
79 desc_msg.append('\n')
80 desc_msg.extend(self.__changes(cs))
81 desc_msg.append('</pre>')
82 return desc_msg
77 83
78 84 def atom(self, repo_name):
79 85 """Produce an atom-1.0 feed via feedgenerator module"""
@@ -87,15 +93,13 b' class FeedController(BaseRepoController)'
87 93 )
88 94
89 95 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
90 desc_msg = []
91 desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
92 desc_msg.append(self.__changes(cs))
93
94 96 feed.add_item(title=self._get_title(cs),
95 97 link=url('changeset_home', repo_name=repo_name,
96 98 revision=cs.raw_id, qualified=True),
97 99 author_name=cs.author,
98 description=''.join(desc_msg))
100 description=''.join(self.__get_desc(cs)),
101 pubdate=cs.date,
102 )
99 103
100 104 response.content_type = feed.mime_type
101 105 return feed.writeString('utf-8')
@@ -112,15 +116,12 b' class FeedController(BaseRepoController)'
112 116 )
113 117
114 118 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
115 desc_msg = []
116 desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
117 desc_msg.append(self.__changes(cs))
118
119 119 feed.add_item(title=self._get_title(cs),
120 120 link=url('changeset_home', repo_name=repo_name,
121 121 revision=cs.raw_id, qualified=True),
122 122 author_name=cs.author,
123 description=''.join(desc_msg),
123 description=''.join(self.__get_desc(cs)),
124 pubdate=cs.date,
124 125 )
125 126
126 127 response.content_type = feed.mime_type
@@ -128,7 +128,7 b' class DiffProcessor(object):'
128 128 """
129 129 _chunk_re = re.compile(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)')
130 130
131 def __init__(self, diff, differ='diff', format='udiff'):
131 def __init__(self, diff, differ='diff', format='gitdiff'):
132 132 """
133 133 :param diff: a text in diff format or generator
134 134 :param format: format of diff passed, `udiff` or `gitdiff`
@@ -171,7 +171,7 b' class DiffProcessor(object):'
171 171
172 172 def _extract_rev(self, line1, line2):
173 173 """
174 Extract the filename and revision hint from a line.
174 Extract the operation (A/M/D), filename and revision hint from a line.
175 175 """
176 176
177 177 try:
@@ -189,11 +189,15 b' class DiffProcessor(object):'
189 189 filename = (old_filename
190 190 if old_filename != '/dev/null' else new_filename)
191 191
192 return filename, new_rev, old_rev
192 operation = 'D' if new_filename == '/dev/null' else None
193 if not operation:
194 operation = 'M' if old_filename != '/dev/null' else 'A'
195
196 return operation, filename, new_rev, old_rev
193 197 except (ValueError, IndexError):
194 198 pass
195 199
196 return None, None, None
200 return None, None, None, None
197 201
198 202 def _parse_gitdiff(self, diffiterator):
199 203 def line_decoder(l):
@@ -278,7 +282,7 b' class DiffProcessor(object):'
278 282 do(line)
279 283 do(next_)
280 284
281 def _parse_udiff(self):
285 def _parse_udiff(self, inline_diff=True):
282 286 """
283 287 Parse the diff an return data for the template.
284 288 """
@@ -293,13 +297,16 b' class DiffProcessor(object):'
293 297 continue
294 298
295 299 chunks = []
296 filename, old_rev, new_rev = \
300 stats = [0, 0]
301 operation, filename, old_rev, new_rev = \
297 302 self._extract_rev(line, lineiter.next())
298 303 files.append({
299 304 'filename': filename,
300 305 'old_revision': old_rev,
301 306 'new_revision': new_rev,
302 'chunks': chunks
307 'chunks': chunks,
308 'operation': operation,
309 'stats': stats,
303 310 })
304 311
305 312 line = lineiter.next()
@@ -331,7 +338,6 b' class DiffProcessor(object):'
331 338 })
332 339
333 340 line = lineiter.next()
334
335 341 while old_line < old_end or new_line < new_end:
336 342 if line:
337 343 command, line = line[0], line[1:]
@@ -345,9 +351,11 b' class DiffProcessor(object):'
345 351 elif command == '+':
346 352 affects_new = True
347 353 action = 'add'
354 stats[0] += 1
348 355 elif command == '-':
349 356 affects_old = True
350 357 action = 'del'
358 stats[1] += 1
351 359 else:
352 360 affects_old = affects_new = True
353 361 action = 'unmod'
@@ -371,13 +379,16 b' class DiffProcessor(object):'
371 379 })
372 380
373 381 line = lineiter.next()
374
375 382 except StopIteration:
376 383 pass
377 384
385 sorter = lambda info: {'A': 0, 'M': 1, 'D': 2}.get(info['operation'])
386 if inline_diff is False:
387 return sorted(files, key=sorter)
388
378 389 # highlight inline changes
379 for _ in files:
380 for chunk in chunks:
390 for diff_data in files:
391 for chunk in diff_data['chunks']:
381 392 lineiter = iter(chunk)
382 393 try:
383 394 while 1:
@@ -391,14 +402,14 b' class DiffProcessor(object):'
391 402 except StopIteration:
392 403 pass
393 404
394 return files
405 return sorted(files, key=sorter)
395 406
396 def prepare(self):
407 def prepare(self, inline_diff=True):
397 408 """
398 409 Prepare the passed udiff for HTML rendering. It'l return a list
399 410 of dicts
400 411 """
401 return self._parse_udiff()
412 return self._parse_udiff(inline_diff=inline_diff)
402 413
403 414 def _safe_id(self, idstring):
404 415 """Make a string safe for including in an id attribute.
@@ -432,7 +443,7 b' class DiffProcessor(object):'
432 443
433 444 def as_html(self, table_class='code-difftable', line_class='line',
434 445 new_lineno_class='lineno old', old_lineno_class='lineno new',
435 code_class='code', enable_comments=False):
446 code_class='code', enable_comments=False, diff_lines=None):
436 447 """
437 448 Return udiff as html table with customized css classes
438 449 """
@@ -448,7 +459,8 b' class DiffProcessor(object):'
448 459 }
449 460 else:
450 461 return label
451 diff_lines = self.prepare()
462 if diff_lines is None:
463 diff_lines = self.prepare()
452 464 _html_empty = True
453 465 _html = []
454 466 _html.append('''<table class="%(table_class)s">\n''' % {
General Comments 0
You need to be logged in to leave comments. Login now