##// END OF EJS Templates
vcs: Minimal change to expose the shadow repository...
vcs: Minimal change to expose the shadow repository Based on my original research, this was the "minimal" starting point. It shows that three concepts are needed for the "repo_name": * From the security standpoint we think of the shadow repository having the same ACL as the target repository of the pull request. This is because the pull request itself is considered to be a part of the target repository. Out of this thought, the variable "acl_repo_name" is used whenever we want to check permissions or when we need the database configuration of the repository. An alternative name would have been "db_repo_name", but the usage for ACL checking is the most important one. * From the web interaction perspective, we need the URL which was originally used to get to the repository. This is because based on this base URL commands can be identified. Especially for Git this is important, so that the commands are correctly recognized. Since the URL is in the focus, this is called "url_repo_name". * Finally we have to deal with the repository on the file system. This is what the VCS layer deal with normally, so this name is called "vcs_repo_name". The original repository interaction is a special case where all three names are the same. When interacting with a pull request, these three names are typically all different. This change is minimal in a sense that it just makes the interaction with a shadow repository barely work, without checking any special constraints yet. This was the starting point for further work on this topic.

File last commit:

r881:aafa0b10 default
r887:175782be default
Show More
test_diffs.py
748 lines | 26.1 KiB | text/x-python | PythonLexer
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2016 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import textwrap
import pytest
from rhodecode.lib.diffs import (
DiffProcessor, wrapped_diff,
NEW_FILENODE, DEL_FILENODE, MOD_FILENODE, RENAMED_FILENODE,
CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE)
from rhodecode.tests.fixture import Fixture
from rhodecode.lib.vcs.backends.git.repository import GitDiff
from rhodecode.lib.vcs.backends.hg.repository import MercurialDiff
from rhodecode.lib.vcs.backends.svn.repository import SubversionDiff
fixture = Fixture()
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 test_diffprocessor_as_html_with_comments():
raw_diff = textwrap.dedent('''
diff --git a/setup.py b/setup.py
index 5b36422..cfd698e 100755
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
#!/usr/bin/python
# Setup file for X
# Copyright (C) No one
-
+x
try:
from setuptools import setup, Extension
except ImportError:
''')
diff = GitDiff(raw_diff)
processor = DiffProcessor(diff)
processor.prepare()
# Note that the cell with the context in line 5 (in the html) has the
# no-comment class, which will prevent the add comment icon to be displayed.
expected_html = textwrap.dedent('''
<table class="code-difftable">
<tr class="line context">
<td class="add-comment-line"><span class="add-comment-content"></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td class="lineno old">...</td>
<td class="lineno new">...</td>
<td class="code no-comment">
<pre>@@ -2,7 +2,7 @@
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o2" class="lineno old"><a href="#setuppy_o2" class="tooltip"
title="Click to select line">2</a></td>
<td id="setuppy_n2" class="lineno new"><a href="#setuppy_n2" class="tooltip"
title="Click to select line">2</a></td>
<td class="code">
<pre>#!/usr/bin/python
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o3" class="lineno old"><a href="#setuppy_o3" class="tooltip"
title="Click to select line">3</a></td>
<td id="setuppy_n3" class="lineno new"><a href="#setuppy_n3" class="tooltip"
title="Click to select line">3</a></td>
<td class="code">
<pre># Setup file for X
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o4" class="lineno old"><a href="#setuppy_o4" class="tooltip"
title="Click to select line">4</a></td>
<td id="setuppy_n4" class="lineno new"><a href="#setuppy_n4" class="tooltip"
title="Click to select line">4</a></td>
<td class="code">
<pre># Copyright (C) No one
</pre>
</td>
</tr>
<tr class="line del">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o5" class="lineno old"><a href="#setuppy_o5" class="tooltip"
title="Click to select line">5</a></td>
<td class="lineno new"><a href="#setuppy_n" class="tooltip"
title="Click to select line"></a></td>
<td class="code">
<pre>
</pre>
</td>
</tr>
<tr class="line add">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td class="lineno old"><a href="#setuppy_o" class="tooltip"
title="Click to select line"></a></td>
<td id="setuppy_n5" class="lineno new"><a href="#setuppy_n5" class="tooltip"
title="Click to select line">5</a></td>
<td class="code">
<pre><ins>x</ins>
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o6" class="lineno old"><a href="#setuppy_o6" class="tooltip"
title="Click to select line">6</a></td>
<td id="setuppy_n6" class="lineno new"><a href="#setuppy_n6" class="tooltip"
title="Click to select line">6</a></td>
<td class="code">
<pre>try:
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o7" class="lineno old"><a href="#setuppy_o7" class="tooltip"
title="Click to select line">7</a></td>
<td id="setuppy_n7" class="lineno new"><a href="#setuppy_n7" class="tooltip"
title="Click to select line">7</a></td>
<td class="code">
<pre> from setuptools import setup, Extension
</pre>
</td>
</tr>
<tr class="line unmod">
<td class="add-comment-line"><span class="add-comment-content"><a href="#"><span class="icon-comment-add"></span></a></span></td><td class="comment-toggle tooltip" title="Toggle Comment Thread"><i class="icon-comment"></i></td>
<td id="setuppy_o8" class="lineno old"><a href="#setuppy_o8" class="tooltip"
title="Click to select line">8</a></td>
<td id="setuppy_n8" class="lineno new"><a href="#setuppy_n8" class="tooltip"
title="Click to select line">8</a></td>
<td class="code">
<pre>except ImportError:
</pre>
</td>
</tr>
</table>
''').strip()
html = processor.as_html(enable_comments=True).replace('\t', ' ')
assert html == expected_html
class TestMixedFilenameEncodings:
@pytest.fixture(scope="class")
def raw_diff(self):
return fixture.load_resource(
'hg_diff_mixed_filename_encodings.diff')
@pytest.fixture
def processor(self, raw_diff):
diff = MercurialDiff(raw_diff)
processor = DiffProcessor(diff)
return processor
def test_filenames_are_decoded_to_unicode(self, processor):
diff_data = processor.prepare()
filenames = [item['filename'] for item in diff_data]
assert filenames == [
u'späcial-utf8.txt', u'sp�cial-cp1252.txt', u'sp�cial-latin1.txt']
def test_raw_diff_is_decoded_to_unicode(self, processor):
diff_data = processor.prepare()
raw_diffs = [item['raw_diff'] for item in diff_data]
new_file_message = u'\nnew file mode 100644\n'
expected_raw_diffs = [
u' a/späcial-utf8.txt b/späcial-utf8.txt' + new_file_message,
u' a/sp�cial-cp1252.txt b/sp�cial-cp1252.txt' + new_file_message,
u' a/sp�cial-latin1.txt b/sp�cial-latin1.txt' + new_file_message]
assert raw_diffs == expected_raw_diffs
def test_as_raw_preserves_the_encoding(self, processor, raw_diff):
assert processor.as_raw() == raw_diff
# TODO: mikhail: format the following data structure properly
DIFF_FIXTURES = [
('hg',
'hg_diff_add_single_binary_file.diff',
[('US Warszawa.jpg', 'A',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {NEW_FILENODE: 'new file 100755',
BIN_FILENODE: 'binary diff hidden'}}),
]),
('hg',
'hg_diff_mod_single_binary_file.diff',
[('US Warszawa.jpg', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {MOD_FILENODE: 'modified file',
BIN_FILENODE: 'binary diff hidden'}}),
]),
('hg',
'hg_diff_mod_single_file_and_rename_and_chmod.diff',
[('README', 'M',
{'added': 3,
'deleted': 0,
'binary': False,
'ops': {MOD_FILENODE: 'modified file',
RENAMED_FILENODE: 'file renamed from README.rst to README',
CHMOD_FILENODE: 'modified file chmod 100755 => 100644'}}),
]),
('hg',
'hg_diff_mod_file_and_rename.diff',
[('README.rst', 'M',
{'added': 3,
'deleted': 0,
'binary': False,
'ops': {MOD_FILENODE: 'modified file',
RENAMED_FILENODE: 'file renamed from README to README.rst'}}),
]),
('hg',
'hg_diff_del_single_binary_file.diff',
[('US Warszawa.jpg', 'D',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {DEL_FILENODE: 'deleted file',
BIN_FILENODE: 'binary diff hidden'}}),
]),
('hg',
'hg_diff_chmod_and_mod_single_binary_file.diff',
[('gravatar.png', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {CHMOD_FILENODE: 'modified file chmod 100644 => 100755',
BIN_FILENODE: 'binary diff hidden'}}),
]),
('hg',
'hg_diff_chmod.diff',
[('file', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {CHMOD_FILENODE: 'modified file chmod 100755 => 100644'}}),
]),
('hg',
'hg_diff_rename_file.diff',
[('file_renamed', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {RENAMED_FILENODE: 'file renamed from file to file_renamed'}}),
]),
('hg',
'hg_diff_rename_and_chmod_file.diff',
[('README', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {CHMOD_FILENODE: 'modified file chmod 100644 => 100755',
RENAMED_FILENODE: 'file renamed from README.rst to README'}}),
]),
('hg',
'hg_diff_binary_and_normal.diff',
[('img/baseline-10px.png', 'A',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {NEW_FILENODE: 'new file 100644',
BIN_FILENODE: 'binary diff hidden'}}),
('js/jquery/hashgrid.js', 'A',
{'added': 340,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100755'}}),
('index.html', 'M',
{'added': 3,
'deleted': 2,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('less/docs.less', 'M',
{'added': 34,
'deleted': 0,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('less/scaffolding.less', 'M',
{'added': 1,
'deleted': 3,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('readme.markdown', 'M',
{'added': 1,
'deleted': 10,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('img/baseline-20px.png', 'D',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {DEL_FILENODE: 'deleted file',
BIN_FILENODE: 'binary diff hidden'}}),
('js/global.js', 'D',
{'added': 0,
'deleted': 75,
'binary': False,
'ops': {DEL_FILENODE: 'deleted file'}})
]),
('git',
'git_diff_chmod.diff',
[('work-horus.xls', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {CHMOD_FILENODE: 'modified file chmod 100644 => 100755'}})
]),
('git',
'git_diff_rename_file.diff',
[('file.xls', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {
RENAMED_FILENODE: 'file renamed from work-horus.xls to file.xls'}})
]),
('git',
'git_diff_mod_single_binary_file.diff',
[('US Warszawa.jpg', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {MOD_FILENODE: 'modified file',
BIN_FILENODE: 'binary diff hidden'}})
]),
('git',
'git_diff_binary_and_normal.diff',
[('img/baseline-10px.png', 'A',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {NEW_FILENODE: 'new file 100644',
BIN_FILENODE: 'binary diff hidden'}}),
('js/jquery/hashgrid.js', 'A',
{'added': 340,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100755'}}),
('index.html', 'M',
{'added': 3,
'deleted': 2,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('less/docs.less', 'M',
{'added': 34,
'deleted': 0,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('less/scaffolding.less', 'M',
{'added': 1,
'deleted': 3,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('readme.markdown', 'M',
{'added': 1,
'deleted': 10,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('img/baseline-20px.png', 'D',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {DEL_FILENODE: 'deleted file',
BIN_FILENODE: 'binary diff hidden'}}),
('js/global.js', 'D',
{'added': 0,
'deleted': 75,
'binary': False,
'ops': {DEL_FILENODE: 'deleted file'}}),
]),
('hg',
'diff_with_diff_data.diff',
[('vcs/backends/base.py', 'M',
{'added': 18,
'deleted': 2,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('vcs/backends/git/repository.py', 'M',
{'added': 46,
'deleted': 15,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('vcs/backends/hg.py', 'M',
{'added': 22,
'deleted': 3,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('vcs/tests/test_git.py', 'M',
{'added': 5,
'deleted': 5,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
('vcs/tests/test_repository.py', 'M',
{'added': 174,
'deleted': 2,
'binary': False,
'ops': {MOD_FILENODE: 'modified file'}}),
]),
('hg',
'hg_diff_copy_file.diff',
[('file2', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {COPIED_FILENODE: 'file copied from file1 to file2'}}),
]),
('hg',
'hg_diff_copy_and_modify_file.diff',
[('file3', 'M',
{'added': 1,
'deleted': 0,
'binary': False,
'ops': {COPIED_FILENODE: 'file copied from file2 to file3',
MOD_FILENODE: 'modified file'}}),
]),
('hg',
'hg_diff_copy_and_chmod_file.diff',
[('file4', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {COPIED_FILENODE: 'file copied from file3 to file4',
CHMOD_FILENODE: 'modified file chmod 100644 => 100755'}}),
]),
('hg',
'hg_diff_copy_chmod_and_edit_file.diff',
[('file5', 'M',
{'added': 2,
'deleted': 1,
'binary': False,
'ops': {COPIED_FILENODE: 'file copied from file4 to file5',
CHMOD_FILENODE: 'modified file chmod 100755 => 100644',
MOD_FILENODE: 'modified file'}})]),
# Diffs to validate rename and copy file with space in its name
('git',
'git_diff_rename_file_with_spaces.diff',
[('file_with_ two spaces.txt', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {
RENAMED_FILENODE: (
'file renamed from file_with_ spaces.txt to file_with_ '
' two spaces.txt')}
}), ]),
('hg',
'hg_diff_rename_file_with_spaces.diff',
[('file_changed _.txt', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {
RENAMED_FILENODE: (
'file renamed from file_ with update.txt to file_changed'
' _.txt')}
}), ]),
('hg',
'hg_diff_copy_file_with_spaces.diff',
[('file_copied_ with spaces.txt', 'M',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {
COPIED_FILENODE: (
'file copied from file_changed_without_spaces.txt to'
' file_copied_ with spaces.txt')}
}),
]),
# special signs from git
('git',
'git_diff_binary_special_files.diff',
[('css/_Icon\\r', 'A',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {NEW_FILENODE: 'new file 100644',
BIN_FILENODE: 'binary diff hidden'}
}),
]),
('git',
'git_diff_binary_special_files_2.diff',
[('css/Icon\\r', 'A',
{'added': 0,
'deleted': 0,
'binary': True,
'ops': {NEW_FILENODE: 'new file 100644', }
}),
]),
# TODO: mikhail: do we still need this?
# (
# 'hg',
# 'large_diff.diff',
# [
# ('.hgignore', 'A', {
# 'deleted': 0, 'binary': False, 'added': 3, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'MANIFEST.in', 'A',
# {'deleted': 0, 'binary': False, 'added': 3, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'README.txt', 'A',
# {'deleted': 0, 'binary': False, 'added': 19, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'development.ini', 'A', {
# 'deleted': 0, 'binary': False, 'added': 116, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'docs/index.txt', 'A', {
# 'deleted': 0, 'binary': False, 'added': 19, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'ez_setup.py', 'A', {
# 'deleted': 0, 'binary': False, 'added': 276, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'hgapp.py', 'A', {
# 'deleted': 0, 'binary': False, 'added': 26, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'hgwebdir.config', 'A', {
# 'deleted': 0, 'binary': False, 'added': 21, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'pylons_app.egg-info/PKG-INFO', 'A', {
# 'deleted': 0, 'binary': False, 'added': 10, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'pylons_app.egg-info/SOURCES.txt', 'A', {
# 'deleted': 0, 'binary': False, 'added': 33, 'ops': {
# 1: 'new file 100644'}}),
# (
# 'pylons_app.egg-info/dependency_links.txt', 'A', {
# 'deleted': 0, 'binary': False, 'added': 1, 'ops': {
# 1: 'new file 100644'}}),
# #TODO:
# ]
# ),
]
DIFF_FIXTURES_WITH_CONTENT = [
(
'hg', 'hg_diff_single_file_change_newline.diff',
[
(
'file_b', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1 @@\n+test_content b\n' # diff
),
],
),
(
'hg', 'hg_diff_double_file_change_newline.diff',
[
(
'file_b', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1 @@\n+test_content b\n' # diff
),
(
'file_c', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1 @@\n+test_content c\n' # diff
),
],
),
(
'hg', 'hg_diff_double_file_change_double_newline.diff',
[
(
'file_b', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1 @@\n+test_content b\n\n' # diff
),
(
'file_c', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1 @@\n+test_content c\n' # diff
),
],
),
(
'hg', 'hg_diff_four_file_change_newline.diff',
[
(
'file', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1,1 @@\n+file\n' # diff
),
(
'file2', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1,1 @@\n+another line\n' # diff
),
(
'file3', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1,1 @@\n+newline\n' # diff
),
(
'file4', # filename
'A', # change
{ # stats
'added': 1,
'deleted': 0,
'binary': False,
'ops': {NEW_FILENODE: 'new file 100644', }
},
'@@ -0,0 +1,1 @@\n+fil4\n\\ No newline at end of file' # diff
),
],
),
]
diff_class = {
'git': GitDiff,
'hg': MercurialDiff,
'svn': SubversionDiff,
}
@pytest.fixture(params=DIFF_FIXTURES)
def diff_fixture(request):
vcs, diff_fixture, expected = request.param
diff_txt = fixture.load_resource(diff_fixture)
diff = diff_class[vcs](diff_txt)
return diff, expected
def test_diff_lib(diff_fixture):
diff, expected_data = diff_fixture
diff_proc = DiffProcessor(diff)
diff_proc_d = diff_proc.prepare()
data = [(x['filename'], x['operation'], x['stats']) for x in diff_proc_d]
assert expected_data == data
@pytest.fixture(params=DIFF_FIXTURES_WITH_CONTENT)
def diff_fixture_w_content(request):
vcs, diff_fixture, expected = request.param
diff_txt = fixture.load_resource(diff_fixture)
diff = diff_class[vcs](diff_txt)
return diff, expected
def test_diff_lib_newlines(diff_fixture_w_content):
diff, expected_data = diff_fixture_w_content
diff_proc = DiffProcessor(diff)
diff_proc_d = diff_proc.prepare()
data = [(x['filename'], x['operation'], x['stats'], x['raw_diff'])
for x in diff_proc_d]
assert expected_data == data