Show More
@@ -20,6 +20,7 b'' | |||||
20 |
|
20 | |||
21 | import logging |
|
21 | import logging | |
22 | import difflib |
|
22 | import difflib | |
|
23 | import string | |||
23 | from itertools import groupby |
|
24 | from itertools import groupby | |
24 |
|
25 | |||
25 | from pygments import lex |
|
26 | from pygments import lex | |
@@ -28,11 +29,11 b' from pygments.lexers.special import Text' | |||||
28 |
|
29 | |||
29 | from rhodecode.lib.helpers import ( |
|
30 | from rhodecode.lib.helpers import ( | |
30 | get_lexer_for_filenode, html_escape, get_custom_lexer) |
|
31 | get_lexer_for_filenode, html_escape, get_custom_lexer) | |
31 | from rhodecode.lib.utils2 import AttributeDict, StrictAttributeDict |
|
32 | from rhodecode.lib.utils2 import AttributeDict, StrictAttributeDict, safe_unicode | |
32 | from rhodecode.lib.vcs.nodes import FileNode |
|
33 | from rhodecode.lib.vcs.nodes import FileNode | |
33 | from rhodecode.lib.vcs.exceptions import VCSError, NodeDoesNotExistError |
|
34 | from rhodecode.lib.vcs.exceptions import VCSError, NodeDoesNotExistError | |
34 | from rhodecode.lib.diff_match_patch import diff_match_patch |
|
35 | from rhodecode.lib.diff_match_patch import diff_match_patch | |
35 | from rhodecode.lib.diffs import LimitedDiffContainer |
|
36 | from rhodecode.lib.diffs import LimitedDiffContainer, DEL_FILENODE, BIN_FILENODE | |
36 | from pygments.lexers import get_lexer_by_name |
|
37 | from pygments.lexers import get_lexer_by_name | |
37 |
|
38 | |||
38 | plain_text_lexer = get_lexer_by_name( |
|
39 | plain_text_lexer = get_lexer_by_name( | |
@@ -506,6 +507,7 b' class DiffSet(object):' | |||||
506 | 'target_mode': patch['stats']['new_mode'], |
|
507 | 'target_mode': patch['stats']['new_mode'], | |
507 | 'limited_diff': isinstance(patch, LimitedDiffContainer), |
|
508 | 'limited_diff': isinstance(patch, LimitedDiffContainer), | |
508 | 'hunks': [], |
|
509 | 'hunks': [], | |
|
510 | 'hunk_ops': None, | |||
509 | 'diffset': self, |
|
511 | 'diffset': self, | |
510 | }) |
|
512 | }) | |
511 |
|
513 | |||
@@ -515,6 +517,30 b' class DiffSet(object):' | |||||
515 | hunkbit.target_file_path = target_file_path |
|
517 | hunkbit.target_file_path = target_file_path | |
516 | filediff.hunks.append(hunkbit) |
|
518 | filediff.hunks.append(hunkbit) | |
517 |
|
519 | |||
|
520 | # Simulate hunk on OPS type line which doesn't really contain any diff | |||
|
521 | # this allows commenting on those | |||
|
522 | actions = [] | |||
|
523 | for op_id, op_text in filediff.patch['stats']['ops'].items(): | |||
|
524 | if op_id == DEL_FILENODE: | |||
|
525 | actions.append(u'file was deleted') | |||
|
526 | elif op_id == BIN_FILENODE: | |||
|
527 | actions.append(u'binary diff hidden') | |||
|
528 | else: | |||
|
529 | actions.append(safe_unicode(op_text)) | |||
|
530 | action_line = u'FILE WITHOUT CONTENT: ' + \ | |||
|
531 | u', '.join(map(string.upper, actions)) or u'UNDEFINED_ACTION' | |||
|
532 | ||||
|
533 | hunk_ops = {'source_length': 0, 'source_start': 0, | |||
|
534 | 'lines': [ | |||
|
535 | {'new_lineno': 0, 'old_lineno': 1, | |||
|
536 | 'action': 'unmod', 'line': action_line} | |||
|
537 | ], | |||
|
538 | 'section_header': u'', 'target_start': 1, 'target_length': 1} | |||
|
539 | ||||
|
540 | hunkbit = self.parse_hunk(hunk_ops, source_file, target_file) | |||
|
541 | hunkbit.source_file_path = source_file_path | |||
|
542 | hunkbit.target_file_path = target_file_path | |||
|
543 | filediff.hunk_ops = hunkbit | |||
518 | return filediff |
|
544 | return filediff | |
519 |
|
545 | |||
520 | def parse_hunk(self, hunk, source_file, target_file): |
|
546 | def parse_hunk(self, hunk, source_file, target_file): |
@@ -149,42 +149,37 b' collapse_all = len(diffset.files) > coll' | |||||
149 | lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] |
|
149 | lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] | |
150 | over_lines_changed_limit = lines_changed > lines_changed_limit |
|
150 | over_lines_changed_limit = lines_changed > lines_changed_limit | |
151 | %> |
|
151 | %> | |
152 | <input ${collapse_all and 'checked' or ''} class="filediff-collapse-state" id="filediff-collapse-${id(filediff)}" type="checkbox"> |
|
152 | ||
|
153 | <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state" id="filediff-collapse-${id(filediff)}" type="checkbox"> | |||
153 | <div |
|
154 | <div | |
154 | class="filediff" |
|
155 | class="filediff" | |
155 | data-f-path="${filediff.patch['filename']}" |
|
156 | data-f-path="${filediff.patch['filename']}" | |
156 |
id="a_${h.FID('', filediff.patch['filename'])}" |
|
157 | id="a_${h.FID('', filediff.patch['filename'])}" | |
|
158 | > | |||
|
159 | ||||
157 |
|
|
160 | <label for="filediff-collapse-${id(filediff)}" class="filediff-heading"> | |
158 |
|
|
161 | <div class="filediff-collapse-indicator"></div> | |
159 |
|
|
162 | ${diff_ops(filediff)} | |
160 |
|
|
163 | </label> | |
161 |
|
|
164 | ${diff_menu(filediff, use_comments=use_comments)} | |
162 |
|
|
165 | <table class="cb cb-diff-${c.diffmode} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}"> | |
|
166 | ||||
|
167 | ## new/deleted/empty content case | |||
163 | %if not filediff.hunks: |
|
168 | % if not filediff.hunks: | |
164 | %for op_id, op_text in filediff.patch['stats']['ops'].items(): |
|
169 | ## Comment container, on "fakes" hunk that contains all data to render comments | |
165 | <tr> |
|
170 | ${render_hunk_lines(c.diffmode, filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments)} | |
166 | <td class="cb-text cb-${op_class(op_id)}" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}> |
|
|||
167 | %if op_id == DEL_FILENODE: |
|
|||
168 | ${_('File was deleted')} |
|
|||
169 | %elif op_id == BIN_FILENODE: |
|
|||
170 | ${_('Binary file hidden')} |
|
|||
171 | %else: |
|
|||
172 | ${op_text} |
|
|||
173 |
|
|
171 | % endif | |
174 | </td> |
|
172 | ||
175 | </tr> |
|
|||
176 | %endfor |
|
|||
177 | %endif |
|
|||
178 |
|
|
173 | %if filediff.limited_diff: | |
179 | <tr class="cb-warning cb-collapser"> |
|
174 | <tr class="cb-warning cb-collapser"> | |
180 | <td class="cb-text" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}> |
|
175 | <td class="cb-text" ${(c.diffmode == 'unified' and 'colspan=4' or 'colspan=6')}> | |
181 | ${_('The requested commit is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a> |
|
176 | ${_('The requested commit is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a> | |
182 | </td> |
|
177 | </td> | |
183 | </tr> |
|
178 | </tr> | |
184 | %else: |
|
179 | %else: | |
185 | %if over_lines_changed_limit: |
|
180 | %if over_lines_changed_limit: | |
186 | <tr class="cb-warning cb-collapser"> |
|
181 | <tr class="cb-warning cb-collapser"> | |
187 | <td class="cb-text" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}> |
|
182 | <td class="cb-text" ${(c.diffmode == 'unified' and 'colspan=4' or 'colspan=6')}> | |
188 | ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)} |
|
183 | ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)} | |
189 | <a href="#" class="cb-expand" |
|
184 | <a href="#" class="cb-expand" | |
190 | onclick="$(this).closest('table').removeClass('cb-collapsed'); return false;">${_('Show them')} |
|
185 | onclick="$(this).closest('table').removeClass('cb-collapsed'); return false;">${_('Show them')} | |
@@ -199,28 +194,20 b' collapse_all = len(diffset.files) > coll' | |||||
199 |
|
194 | |||
200 | %for hunk in filediff.hunks: |
|
195 | % for hunk in filediff.hunks: | |
201 |
|
|
196 | <tr class="cb-hunk"> | |
202 |
|
|
197 | <td ${(c.diffmode == 'unified' and 'colspan=3' or '')}> | |
203 |
|
|
198 | ## TODO: dan: add ajax loading of more context here | |
204 |
|
|
199 | ## <a href="#"> | |
205 |
|
|
200 | <i class="icon-more"></i> | |
206 |
|
|
201 | ## </a> | |
207 |
|
|
202 | </td> | |
208 |
|
|
203 | <td ${(c.diffmode == 'sideside' and 'colspan=5' or '')}> | |
209 |
|
|
204 | @@ | |
210 |
|
|
205 | -${hunk.source_start},${hunk.source_length} | |
211 |
|
|
206 | +${hunk.target_start},${hunk.target_length} | |
212 |
|
|
207 | ${hunk.section_header} | |
213 |
|
|
208 | </td> | |
214 |
|
|
209 | </tr> | |
215 | %if c.diffmode == 'unified': |
|
210 | ${render_hunk_lines(c.diffmode, hunk, use_comments=use_comments, inline_comments=inline_comments)} | |
216 | ${render_hunk_lines_unified(hunk, use_comments=use_comments, inline_comments=inline_comments)} |
|
|||
217 | %elif c.diffmode == 'sideside': |
|
|||
218 | ${render_hunk_lines_sideside(hunk, use_comments=use_comments, inline_comments=inline_comments)} |
|
|||
219 | %else: |
|
|||
220 | <tr class="cb-line"> |
|
|||
221 | <td>unknown diff mode</td> |
|
|||
222 | </tr> |
|
|||
223 | %endif |
|
|||
224 |
|
|
211 | % endfor | |
225 |
|
212 | |||
226 | <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %> |
|
213 | <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %> | |
@@ -292,7 +279,7 b' collapse_all = len(diffset.files) > coll' | |||||
292 | display_state = '' |
|
279 | display_state = '' | |
293 | %> |
|
280 | %> | |
294 | <div class="filediffs filediff-outdated" style="${display_state}"> |
|
281 | <div class="filediffs filediff-outdated" style="${display_state}"> | |
295 | <input ${collapse_all and 'checked' or ''} class="filediff-collapse-state" id="filediff-collapse-${id(filename)}" type="checkbox"> |
|
282 | <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state" id="filediff-collapse-${id(filename)}" type="checkbox"> | |
296 | <div class="filediff" data-f-path="${filename}" id="a_${h.FID('', filename)}"> |
|
283 | <div class="filediff" data-f-path="${filename}" id="a_${h.FID('', filename)}"> | |
297 | <label for="filediff-collapse-${id(filename)}" class="filediff-heading"> |
|
284 | <label for="filediff-collapse-${id(filename)}" class="filediff-heading"> | |
298 | <div class="filediff-collapse-indicator"></div> |
|
285 | <div class="filediff-collapse-indicator"></div> | |
@@ -714,6 +701,20 b' def get_comments_for(diff_type, comments' | |||||
714 | %endfor |
|
701 | %endfor | |
715 | </%def> |
|
702 | </%def> | |
716 |
|
703 | |||
|
704 | ||||
|
705 | <%def name="render_hunk_lines(diff_mode, hunk, use_comments, inline_comments)"> | |||
|
706 | % if diff_mode == 'unified': | |||
|
707 | ${render_hunk_lines_unified(hunk, use_comments=use_comments, inline_comments=inline_comments)} | |||
|
708 | % elif diff_mode == 'sideside': | |||
|
709 | ${render_hunk_lines_sideside(hunk, use_comments=use_comments, inline_comments=inline_comments)} | |||
|
710 | % else: | |||
|
711 | <tr class="cb-line"> | |||
|
712 | <td>unknown diff mode</td> | |||
|
713 | </tr> | |||
|
714 | % endif | |||
|
715 | </%def> | |||
|
716 | ||||
|
717 | ||||
717 | <%def name="render_add_comment_button()"> |
|
718 | <%def name="render_add_comment_button()"> | |
718 | <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)"> |
|
719 | <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)"> | |
719 | <span><i class="icon-comment"></i></span> |
|
720 | <span><i class="icon-comment"></i></span> |
General Comments 0
You need to be logged in to leave comments.
Login now