<%namespace name="base" file="/base/base.mako"/> <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/> <%def name="diff_line_anchor(commit, filename, line, type)"><% return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line) %> <%def name="action_class(action)"> <% return { '-': 'cb-deletion', '+': 'cb-addition', ' ': 'cb-context', }.get(action, 'cb-empty') %> <%def name="op_class(op_id)"> <% return { DEL_FILENODE: 'deletion', # file deleted BIN_FILENODE: 'warning' # binary diff hidden }.get(op_id, 'addition') %> <%def name="render_diffset(diffset, commit=None, # collapse all file diff entries when there are more than this amount of files in the diff collapse_when_files_over=20, # collapse lines in the diff when more than this amount of lines changed in the file diff lines_changed_limit=500, # add a ruler at to the output ruler_at_chars=0, # show inline comments use_comments=False, # disable new comments disable_new_comments=False, # special file-comments that were deleted in previous versions # it's used for showing outdated comments for deleted files in a PR deleted_files_comments=None, # for cache purpose inline_comments=None, # additional menu for PRs pull_request_menu=None, # show/hide todo next to comments show_todos=True, )"> <% diffset_container_id = h.md5_safe(diffset.target_ref) collapse_all = len(diffset.files) > collapse_when_files_over active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None)) from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE %> %if use_comments: ## Template for injecting comments
${inline_comments_container([])}
%if not c.rhodecode_user.is_default: ## render template for inline comments ${commentblock.comment_form(form_type='inline')} %endif
%endif %if c.user_session_attrs["diffmode"] == 'sideside': %endif %if ruler_at_chars: %endif
## expand/collapse action ## todos % if show_todos and getattr(c, 'at_version', None):
TODOs: ${_('not available in this view')}
% elif show_todos:
% if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'): TODOs: % if c.unresolved_comments: ${_('{} unresolved').format(len(c.unresolved_comments))} % else: ${_('0 unresolved')} % endif ${_('{} Resolved').format(len(c.resolved_comments))} % endif
% endif ## ## comments ##
##
## % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'): ## COMMENTS: ## % if c.comments: ## ${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}, ## % else: ## ${_('0 General')} ## % endif ## ## % if c.inline_cnt: ## ${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)} ## ## % else: ## ${_('0 Inline')} ## % endif ## % endif ## ## % if pull_request_menu: ## <% ## outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver'] ## %> ## ## % if outdated_comm_count_ver: ## ## (${_("{} Outdated").format(outdated_comm_count_ver)}) ## ## | ${_('show outdated')} ## ## % else: ## (${_("{} Outdated").format(outdated_comm_count_ver)}) ## % endif ## ## % endif ## ##
##
% if diffset.limited_diff:

${_('The requested changes are too big and content was truncated.')} ${_('Show full diff')}

% endif
% if hasattr(c, 'unresolved_comments') and c.unresolved_comments: % for co in c.unresolved_comments: ${('' if loop.last else ',')} % endfor % endif
%if diffset.has_hidden_changes:

${_('Some changes may be hidden')}

%elif not diffset.files:

${_('No files')}

%endif
## initial value could be marked as False later on <% over_lines_changed_limit = False %> %for i, filediff in enumerate(diffset.files): %if filediff.source_file_path and filediff.target_file_path: %if filediff.source_file_path != filediff.target_file_path: ## file was renamed, or copied %if RENAMED_FILENODE in filediff.patch['stats']['ops']: <% final_file_name = h.literal('{} {}'.format(filediff.target_file_path, filediff.source_file_path)) final_path = filediff.target_file_path %> %elif COPIED_FILENODE in filediff.patch['stats']['ops']: <% final_file_name = h.literal('{} {}'.format(filediff.target_file_path, filediff.source_file_path)) final_path = filediff.target_file_path %> %endif %else: ## file was modified <% final_file_name = filediff.source_file_path final_path = final_file_name %> %endif %else: %if filediff.source_file_path: ## file was deleted <% final_file_name = filediff.source_file_path final_path = final_file_name %> %else: ## file was added <% final_file_name = filediff.target_file_path final_path = final_file_name %> %endif %endif <% lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] over_lines_changed_limit = lines_changed > lines_changed_limit %> ## anchor with support of sticky header
${diff_menu(filediff, use_comments=use_comments)} ## new/deleted/empty content case % if not filediff.hunks: ## Comment container, on "fakes" hunk that contains all data to render comments ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} % endif %if filediff.limited_diff: %else: %if over_lines_changed_limit: %endif %endif % for hunk in filediff.hunks: ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} % endfor <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %> ## outdated comments that do not fit into currently displayed lines % for lineno, comments in unmatched_comments.items(): %if c.user_session_attrs["diffmode"] == 'unified': % if loop.index == 0: % endif %elif c.user_session_attrs["diffmode"] == 'sideside': % if loop.index == 0: % endif %endif % endfor
${_('The requested commit or file is too big and content was truncated.')} ${_('Show full diff')}
${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)} ${_('Show them')} ${_('Hide them')}
## TODO: dan: add ajax loading of more context here ## ## @@ -${hunk.source_start},${hunk.source_length} +${hunk.target_start},${hunk.target_length} ${hunk.section_header}
${_('Unmatched/outdated inline comments below')}
${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
${_('Unmatched/outdated inline comments below')}
${_('Unmatched/outdated comments below')}
% if lineno.startswith('o'): ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} % endif % if lineno.startswith('n'): ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} % endif
%endfor ## outdated comments that are made for a file that has been deleted % for filename, comments_dict in (deleted_files_comments or {}).items(): <% display_state = 'display: none' open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False] if open_comments_in_file: display_state = '' fid = str(id(filename)) %>
% if c.user_session_attrs["diffmode"] == 'unified': %endif %if c.user_session_attrs["diffmode"] == 'unified': %elif c.user_session_attrs["diffmode"] == 'sideside': %endif
${_('This file was removed from diff during updates to this pull-request.')}
${_('There are still outdated/unresolved comments attached to it.')}
${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
% endfor
<%def name="diff_ops(file_name, filediff)"> <% from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE %> ${file_name} ## ops pills %if filediff.limited_diff: limited diff %endif %if NEW_FILENODE in filediff.patch['stats']['ops']: created %if filediff['target_mode'].startswith('120'): symlink %else: ${nice_mode(filediff['target_mode'])} %endif %endif %if RENAMED_FILENODE in filediff.patch['stats']['ops']: renamed %endif %if COPIED_FILENODE in filediff.patch['stats']['ops']: copied %endif %if DEL_FILENODE in filediff.patch['stats']['ops']: removed %endif %if CHMOD_FILENODE in filediff.patch['stats']['ops']: ${nice_mode(filediff['source_mode'])} ➡ ${nice_mode(filediff['target_mode'])} %endif %if BIN_FILENODE in filediff.patch['stats']['ops']: binary %if MOD_FILENODE in filediff.patch['stats']['ops']: modified %endif %endif ${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']} ${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)} <%def name="nice_mode(filemode)"> ${(filemode.startswith('100') and filemode[3:] or filemode)} <%def name="diff_menu(filediff, use_comments=False)">
%if filediff.diffset.source_ref: ## FILE BEFORE CHANGES %if filediff.operation in ['D', 'M']: ${_('Show file before')} | %else: ${_('Show file before')} | %endif ## FILE AFTER CHANGES %if filediff.operation in ['A', 'M']: ${_('Show file after')} %else: ${_('Show file after')} %endif % if use_comments: | ${_('Hide comments')} % endif %endif
<%def name="inline_comments_container(comments, active_pattern_entries=None, line_no='', f_path='')">
%for comment in comments: ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)} %endfor <% extra_class = '' extra_style = '' if comments and comments[-1].outdated_at_version(c.at_version_num): extra_class = ' comment-outdated' extra_style = 'display: none;' %>
% if c.rhodecode_user.username != h.DEFAULT_USER: ${base.gravatar(c.rhodecode_user.email, 20, tooltip=True, user=c.rhodecode_user)} % endif
% if c.rhodecode_user.username != h.DEFAULT_USER: ## initial reply button, some JS logic can append here a FORM to leave a first comment. % endif
##% endif
<%! def get_inline_comments(comments, filename): if hasattr(filename, 'str_path'): filename = filename.str_path if not isinstance(filename, str): return None if comments and filename in comments: return comments[filename] return None def get_comments_for(diff_type, comments, filename, line_version, line_number): if hasattr(filename, 'str_path'): filename = filename.str_path if not isinstance(filename, str): return None file_comments = get_inline_comments(comments, filename) if file_comments is None: return None line_key = f'{line_version}{line_number}' ## e.g o37, n12 if line_key in file_comments: data = file_comments.pop(line_key) return data %> <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> <% chunk_count = 1 %> %for loop_obj, item in h.looper(hunk.sideside): <% line = item i = loop_obj.index prev_line = loop_obj.previous old_line_anchor, new_line_anchor = None, None if line.original.lineno: old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o') if line.modified.lineno: new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n') line_action = line.modified.action or line.original.action prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action) %> <% line_old_comments, line_old_comments_no_drafts = None, None %> %if line.original.get_comment_args: <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) line_old_comments_no_drafts = [c for c in line_old_comments if not c.draft] if line_old_comments else [] has_outdated = any([x.outdated for x in line_old_comments_no_drafts]) %> %endif %if line_old_comments_no_drafts: % if has_outdated: % else: % endif %endif %if line.original.lineno: ${line.original.lineno} %endif <% line_no = 'o{}'.format(line.original.lineno) %> %if use_comments and line.original.lineno: ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} %endif ${line.original.content or '' | n} %if use_comments and line.original.lineno and line_old_comments: ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} %endif
<% line_new_comments, line_new_comments_no_drafts = None, None %> %if line.modified.get_comment_args: <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) line_new_comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else [] has_outdated = any([x.outdated for x in line_new_comments_no_drafts]) %> %endif %if line_new_comments_no_drafts: % if has_outdated: % else: % endif %endif
%if line.modified.lineno: ${line.modified.lineno} %endif <% line_no = 'n{}'.format(line.modified.lineno) %> %if use_comments and line.modified.lineno: ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} %endif ${line.modified.content or '' | n} % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']: <% chunk_count +=1 %> % endif %if use_comments and line.modified.lineno and line_new_comments: ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} %endif %endfor <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> %for old_line_no, new_line_no, action, content, comments_args in hunk.unified: <% old_line_anchor, new_line_anchor = None, None if old_line_no: old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o') if new_line_no: new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n') %>
<% comments, comments_no_drafts = None, None %> %if comments_args: <% comments = get_comments_for('unified', inline_comments, *comments_args) comments_no_drafts = [c for c in line_new_comments if not c.draft] if line_new_comments else [] has_outdated = any([x.outdated for x in comments_no_drafts]) %> %endif % if comments_no_drafts: % if has_outdated: % else: % endif % endif
%if old_line_anchor: ${old_line_no} %endif %if new_line_anchor: ${new_line_no} %endif <% line_no = '{}{}'.format(new_line_no and 'n' or 'o', new_line_no or old_line_no) %> %if use_comments: ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} %endif ${content or '' | n} %if use_comments and comments: ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} %endif %endfor <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)"> % if diff_mode == 'unified': ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} % elif diff_mode == 'sideside': ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} % else: unknown diff mode % endif file changes <%def name="render_add_comment_button(line_no='', f_path='')"> % if not c.rhodecode_user.is_default: % endif <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)"> <% diffset_container_id = h.md5_safe(diffset.target_ref) %>
## auto adjustable
% if diffset: %if diffset.limited_diff: <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %> %else: <% file_placeholder = h.literal(_ungettext('%(num)s file changed: %(linesadd)s inserted, %(linesdel)s deleted', '%(num)s files changed: %(linesadd)s inserted, %(linesdel)s deleted', diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %> %endif ## case on range-diff placeholder needs to be updated % if range_diff_on is True: <% file_placeholder = _('Disabled on range diff') %> % endif % endif