def test_wrapped_diff_limited_file_diff(vcsbackend_random): vcsbackend = vcsbackend_random repo = vcsbackend.create_repo() vcsbackend.add_file(repo, 'a_file', content="line 1\nline 2\nline3\n") commit = repo.get_commit() file_node = commit.get_node('a_file') # Only limit the file diff to trigger the code path result = wrapped_diff( None, file_node, diff_limit=10000, file_limit=1) data = result[5] # Verify that the limits were applied assert data['exceeds_limit'] is True assert data['is_limited_diff'] is True
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) diff1 = request.GET.get('diff1', '') diff2 = request.GET.get('diff2', '') c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] #special case if we want a show rev only, it's impl here #to reduce JS and callbacks if request.GET.get('show_rev'): if str2bool(request.GET.get('annotate', 'False')): _url = url('files_annotate_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) else: _url = url('files_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) return redirect(_url) try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) if node1.is_dir(): raise NodeError('%s path is a %s not a file' % (node1, type(node1))) except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset(cs=diff1, revision=c.changeset_1.revision, repo=c.rhodecode_repo) node1 = FileNode(f_path, '', changeset=c.changeset_1) else: c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) node1 = FileNode(f_path, '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) if node2.is_dir(): raise NodeError('%s path is a %s not a file' % (node2, type(node2))) except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset(cs=diff2, revision=c.changeset_2.revision, repo=c.rhodecode_repo) node2 = FileNode(f_path, '', changeset=c.changeset_2) else: c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) node2 = FileNode(f_path, '', changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) return redirect(url('files_home', repo_name=c.repo_name, f_path=f_path)) if c.action == 'download': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ( 'attachment; filename=%s' % diff_name ) return diff.as_raw() elif c.action == 'raw': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') response.content_type = 'text/plain' return diff.as_raw() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = request.GET.get('fulldiff') or self.cut_off_limit _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1, filenode_new=node2, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False) op = '' filename = node1.path cs_changes = { 'fid': [cs1, cs2, op, filename, diff, st] } c.changes = cs_changes return render('files/file_diff.html')
class ChangesetController(BaseRepoController): @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def __before__(self): super(ChangesetController, self).__before__() c.affected_files_cut_off = 60 def index(self, revision): c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url limit_off = request.GET.get('fulldiff') #get ranges of revisions if preset rev_range = revision.split('...')[:2] enable_comments = True try: if len(rev_range) == 2: enable_comments = False rev_start = rev_range[0] rev_end = rev_range[1] rev_ranges = c.rhodecode_repo.get_changesets(start=rev_start, end=rev_end) else: rev_ranges = [c.rhodecode_repo.get_changeset(revision)] c.cs_ranges = list(rev_ranges) if not c.cs_ranges: raise RepositoryError('Changeset range returned empty result') except (RepositoryError, ChangesetDoesNotExistError, Exception), e: log.error(traceback.format_exc()) h.flash(str(e), category='warning') return redirect(url('home')) c.changes = OrderedDict() c.lines_added = 0 # count of lines added c.lines_deleted = 0 # count of lines removes cumulative_diff = 0 c.cut_off = False # defines if cut off limit is reached c.comments = [] c.inline_comments = [] c.inline_cnt = 0 # Iterate over ranges (default changeset view is always one changeset) for changeset in c.cs_ranges: c.comments.extend(ChangesetCommentsModel()\ .get_comments(c.rhodecode_db_repo.repo_id, changeset.raw_id)) inlines = ChangesetCommentsModel()\ .get_inline_comments(c.rhodecode_db_repo.repo_id, changeset.raw_id) c.inline_comments.extend(inlines) c.changes[changeset.raw_id] = [] try: changeset_parent = changeset.parents[0] except IndexError: changeset_parent = None #================================================================== # ADDED FILES #================================================================== for node in changeset.added: fid = h.FID(revision, node.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = self.cut_off_limit if cumulative_diff > self.cut_off_limit: lim = -1 if limit_off is None else None size, cs1, cs2, diff, st = wrapped_diff( filenode_old=None, filenode_new=node, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=enable_comments) cumulative_diff += size c.lines_added += st[0] c.lines_deleted += st[1] c.changes[changeset.raw_id].append( ('added', node, diff, cs1, cs2, st)) #================================================================== # CHANGED FILES #================================================================== for node in changeset.changed: try: filenode_old = changeset_parent.get_node(node.path) except ChangesetError: log.warning('Unable to fetch parent node for diff') filenode_old = FileNode(node.path, '', EmptyChangeset()) fid = h.FID(revision, node.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = self.cut_off_limit if cumulative_diff > self.cut_off_limit: lim = -1 if limit_off is None else None size, cs1, cs2, diff, st = wrapped_diff( filenode_old=filenode_old, filenode_new=node, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=enable_comments) cumulative_diff += size c.lines_added += st[0] c.lines_deleted += st[1] c.changes[changeset.raw_id].append( ('changed', node, diff, cs1, cs2, st)) #================================================================== # REMOVED FILES #================================================================== for node in changeset.removed: c.changes[changeset.raw_id].append( ('removed', node, None, None, None, (0, 0))) # count inline comments for path, lines in c.inline_comments: for comments in lines.values(): c.inline_cnt += len(comments) if len(c.cs_ranges) == 1: c.changeset = c.cs_ranges[0] c.changes = c.changes[c.changeset.raw_id] return render('changeset/changeset.html') else: return render('changeset/changeset_range.html')
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) diff1 = request.GET.get('diff1', '') diff2 = request.GET.get('diff2', '') c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] #special case if we want a show rev only, it's impl here #to reduce JS and callbacks if request.GET.get('show_rev'): if str2bool(request.GET.get('annotate', 'False')): _url = url('files_annotate_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) else: _url = url('files_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) return redirect(_url) try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset(cs=diff1, revision=c.changeset_1.revision, repo=c.rhodecode_repo) node1 = FileNode(f_path, '', changeset=c.changeset_1) else: c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) node1 = FileNode(f_path, '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset(cs=diff2, revision=c.changeset_2.revision, repo=c.rhodecode_repo) node2 = FileNode(f_path, '', changeset=c.changeset_2) else: c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) node2 = FileNode(f_path, '', changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) return redirect(url('files_home', repo_name=c.repo_name, f_path=f_path)) if c.action == 'download': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ( 'attachment; filename=%s' % diff_name ) return diff.as_raw() elif c.action == 'raw': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') response.content_type = 'text/plain' return diff.as_raw() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = request.GET.get('fulldiff') or self.cut_off_limit _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1, filenode_new=node2, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False) op = '' filename = node1.path cs_changes = { 'fid': [cs1, cs2, op, filename, diff, st] } c.changes = cs_changes return render('files/file_diff.html')
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) diff1 = request.GET.get('diff1', '') diff2 = request.GET.get('diff2', '') c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) node1 = c.changeset_1.get_node(f_path) else: c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) node1 = FileNode('.', '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) node2 = c.changeset_2.get_node(f_path) else: c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) node2 = FileNode('.', '', changeset=c.changeset_2) except RepositoryError: return redirect(url('files_home', repo_name=c.repo_name, f_path=f_path)) if c.action == 'download': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ( 'attachment; filename=%s' % diff_name ) return diff.raw_diff() elif c.action == 'raw': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') response.content_type = 'text/plain' return diff.raw_diff() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = request.GET.get('fulldiff') or self.cut_off_limit _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1, filenode_new=node2, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False) c.changes = [('', node2, diff, cs1, cs2, st,)] return render('files/file_diff.html')
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) diff1 = request.GET.get('diff1', '') diff2 = request.GET.get('diff2', '') c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) node1 = c.changeset_1.get_node(f_path) else: c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) node1 = FileNode('.', '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) node2 = c.changeset_2.get_node(f_path) else: c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) node2 = FileNode('.', '', changeset=c.changeset_2) except RepositoryError: return redirect( url('files_home', repo_name=c.repo_name, f_path=f_path)) if c.action == 'download': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ('attachment; filename=%s' % diff_name) return diff.raw_diff() elif c.action == 'raw': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') response.content_type = 'text/plain' return diff.raw_diff() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = request.GET.get('fulldiff') or self.cut_off_limit _, cs1, cs2, diff, st = diffs.wrapped_diff( filenode_old=node1, filenode_new=node2, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False) c.changes = [( '', node2, diff, cs1, cs2, st, )] return render('files/file_diff.html')
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get("ignorews") == "1" line_context = request.GET.get("context", 3) diff1 = request.GET.get("diff1", "") diff2 = request.GET.get("diff2", "") c.action = request.GET.get("diff") c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] # special case if we want a show rev only, it's impl here # to reduce JS and callbacks if request.GET.get("show_rev"): if str2bool(request.GET.get("annotate", "False")): _url = url("files_annotate_home", repo_name=c.repo_name, revision=diff1, f_path=c.f_path) else: _url = url("files_home", repo_name=c.repo_name, revision=diff1, f_path=c.f_path) return redirect(_url) try: if diff1 not in ["", None, "None", "0" * 12, "0" * 40]: c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) if node1.is_dir(): raise NodeError("%s path is a %s not a file" % (node1, type(node1))) except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset(cs=diff1, revision=c.changeset_1.revision, repo=c.rhodecode_repo) node1 = FileNode(f_path, "", changeset=c.changeset_1) else: c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) node1 = FileNode(f_path, "", changeset=c.changeset_1) if diff2 not in ["", None, "None", "0" * 12, "0" * 40]: c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) if node2.is_dir(): raise NodeError("%s path is a %s not a file" % (node2, type(node2))) except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset(cs=diff2, revision=c.changeset_2.revision, repo=c.rhodecode_repo) node2 = FileNode(f_path, "", changeset=c.changeset_2) else: c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) node2 = FileNode(f_path, "", changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) return redirect(url("files_home", repo_name=c.repo_name, f_path=f_path)) if c.action == "download": _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format="gitdiff") diff_name = "%s_vs_%s.diff" % (diff1, diff2) response.content_type = "text/plain" response.content_disposition = "attachment; filename=%s" % diff_name return diff.as_raw() elif c.action == "raw": _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format="gitdiff") response.content_type = "text/plain" return diff.as_raw() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) lim = request.GET.get("fulldiff") or self.cut_off_limit _, cs1, cs2, diff, st = diffs.wrapped_diff( filenode_old=node1, filenode_new=node2, cut_off_limit=lim, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False, ) op = "" filename = node1.path cs_changes = {"fid": [cs1, cs2, op, filename, diff, st]} c.changes = cs_changes return render("files/file_diff.html")
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) diff1 = request.GET.get('diff1', '') path1, diff1 = parse_path_ref(diff1, default_path=f_path) diff2 = request.GET.get('diff2', '') c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] if not any((diff1, diff2)): h.flash( 'Need query parameter "diff1" or "diff2" to generate a diff.', category='error') raise HTTPBadRequest() # special case if we want a show commit_id only, it's impl here # to reduce JS and callbacks if request.GET.get('show_rev') and diff1: if str2bool(request.GET.get('annotate', 'False')): _url = url('files_annotate_home', repo_name=c.repo_name, revision=diff1, f_path=path1) else: _url = url('files_home', repo_name=c.repo_name, revision=diff1, f_path=path1) return redirect(_url) try: node1 = self._get_file_node(diff1, path1) node2 = self._get_file_node(diff2, f_path) except (RepositoryError, NodeError): log.exception("Exception while trying to get node from repository") return redirect( url('files_home', repo_name=c.repo_name, f_path=f_path)) if all( isinstance(node.commit, EmptyCommit) for node in (node1, node2)): raise HTTPNotFound c.commit_1 = node1.commit c.commit_2 = node2.commit if c.action == 'download': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ('attachment; filename=%s' % (diff_name, )) charset = self._get_default_encoding() if charset: response.charset = charset return diff.as_raw() elif c.action == 'raw': _diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff = diffs.DiffProcessor(_diff, format='gitdiff') response.content_type = 'text/plain' charset = self._get_default_encoding() if charset: response.charset = charset return diff.as_raw() else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) __, commit1, commit2, diff, st, data = diffs.wrapped_diff( filenode_old=node1, filenode_new=node2, diff_limit=self.cut_off_limit_diff, file_limit=self.cut_off_limit_file, show_full_diff=request.GET.get('fulldiff'), ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, ) c.lines_added = data['stats']['added'] if data else 0 c.lines_deleted = data['stats']['deleted'] if data else 0 c.files = [data] c.commit_ranges = [c.commit_1, c.commit_2] c.ancestor = None c.statuses = [] c.target_repo = c.rhodecode_db_repo c.filename1 = node1.path c.filename = node2.path c.binary_file = node1.is_binary or node2.is_binary operation = data['operation'] if data else '' commit_changes = { # TODO: it's passing the old file to the diff to keep the # standard but this is not being used for this template, # but might need both files in the future or a more standard # way to work with that 'fid': [commit1, commit2, operation, c.filename, diff, st, data] } c.changes = commit_changes return render('files/file_diff.html')