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 = |
|
|
53 | self.feed_nr = 20 | |
|
53 | 54 | |
|
54 | 55 | def _get_title(self, cs): |
|
55 |
return " |
|
|
56 |
|
|
|
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 |
|
|
|
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( |
|
|
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( |
|
|
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=' |
|
|
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 |
|
|
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