1184 lines
35 KiB
Python
1184 lines
35 KiB
Python
# Copyright (C) 2010-2024 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 mock
|
||
import pytest
|
||
|
||
from rhodecode.lib.codeblocks import DiffSet
|
||
from rhodecode.lib.diffs import (
|
||
DiffProcessor,
|
||
NEW_FILENODE,
|
||
DEL_FILENODE,
|
||
MOD_FILENODE,
|
||
RENAMED_FILENODE,
|
||
CHMOD_FILENODE,
|
||
BIN_FILENODE,
|
||
COPIED_FILENODE,
|
||
)
|
||
|
||
from rhodecode.lib.utils2 import AttributeDict
|
||
from rhodecode.lib.vcs.backends.git import GitCommit
|
||
from rhodecode.tests.fixtures.rc_fixture import Fixture
|
||
from rhodecode.tests import no_newline_id_generator
|
||
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()
|
||
|
||
|
||
class TestMixedFilenameEncodings(object):
|
||
@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, diff_format="newdiff")
|
||
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 == ["späcial-utf8.txt", "sp<EFBFBD>cial-cp1252.txt", "sp<EFBFBD>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 = "\nnew file mode 100644\n"
|
||
expected_raw_diffs = [
|
||
" a/späcial-utf8.txt b/späcial-utf8.txt" + new_file_message,
|
||
" a/sp<73>cial-cp1252.txt b/sp<73>cial-cp1252.txt" + new_file_message,
|
||
" a/sp<73>cial-latin1.txt b/sp<73>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,
|
||
"old_mode": "",
|
||
"new_mode": "100755",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"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,
|
||
"old_mode": "100755",
|
||
"new_mode": "100644",
|
||
"renamed": ("README.rst", "README"),
|
||
"ops": {
|
||
MOD_FILENODE: "modified file",
|
||
RENAMED_FILENODE: "file renamed from README.rst to README",
|
||
CHMOD_FILENODE: "modified file chmod 100755 => 100644",
|
||
},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"hg",
|
||
"hg_diff_no_newline.diff",
|
||
[
|
||
(
|
||
"server.properties",
|
||
"M",
|
||
{
|
||
"added": 2,
|
||
"deleted": 1,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"hg",
|
||
"hg_diff_mod_file_and_rename.diff",
|
||
[
|
||
(
|
||
"README.rst",
|
||
"M",
|
||
{
|
||
"added": 3,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"renamed": ("README", "README.rst"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"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,
|
||
"old_mode": "100644",
|
||
"new_mode": "100755",
|
||
"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,
|
||
"old_mode": "100755",
|
||
"new_mode": "100644",
|
||
"ops": {CHMOD_FILENODE: "modified file chmod 100755 => 100644"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"hg",
|
||
"hg_diff_rename_file.diff",
|
||
[
|
||
(
|
||
"file_renamed",
|
||
"M",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"renamed": ("file", "file_renamed"),
|
||
"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,
|
||
"old_mode": "100644",
|
||
"new_mode": "100755",
|
||
"renamed": ("README.rst", "README"),
|
||
"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,
|
||
"new_mode": "100644",
|
||
"old_mode": "",
|
||
"ops": {NEW_FILENODE: "new file 100644", BIN_FILENODE: "binary diff hidden"},
|
||
},
|
||
),
|
||
(
|
||
"js/jquery/hashgrid.js",
|
||
"A",
|
||
{
|
||
"added": 340,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"new_mode": "100755",
|
||
"old_mode": "",
|
||
"ops": {NEW_FILENODE: "new file 100755"},
|
||
},
|
||
),
|
||
(
|
||
"index.html",
|
||
"M",
|
||
{
|
||
"added": 3,
|
||
"deleted": 2,
|
||
"binary": False,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"less/docs.less",
|
||
"M",
|
||
{
|
||
"added": 34,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"less/scaffolding.less",
|
||
"M",
|
||
{
|
||
"added": 1,
|
||
"deleted": 3,
|
||
"binary": False,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"readme.markdown",
|
||
"M",
|
||
{
|
||
"added": 1,
|
||
"deleted": 10,
|
||
"binary": False,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"img/baseline-20px.png",
|
||
"D",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {DEL_FILENODE: "deleted file", BIN_FILENODE: "binary diff hidden"},
|
||
},
|
||
),
|
||
(
|
||
"js/global.js",
|
||
"D",
|
||
{
|
||
"added": 0,
|
||
"deleted": 75,
|
||
"binary": False,
|
||
"new_mode": "",
|
||
"old_mode": "",
|
||
"ops": {DEL_FILENODE: "deleted file"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"git",
|
||
"git_diff_chmod.diff",
|
||
[
|
||
(
|
||
"work-horus.xls",
|
||
"M",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"old_mode": "100644",
|
||
"new_mode": "100755",
|
||
"ops": {CHMOD_FILENODE: "modified file chmod 100644 => 100755"},
|
||
},
|
||
)
|
||
],
|
||
),
|
||
(
|
||
"git",
|
||
"git_diff_js_chars.diff",
|
||
[
|
||
(
|
||
'\\"><img src=x onerror=prompt(0)>/\\"><img src=x onerror=prompt(1)>.txt',
|
||
"M",
|
||
{
|
||
"added": 1,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
)
|
||
],
|
||
),
|
||
(
|
||
"git",
|
||
"git_diff_rename_file.diff",
|
||
[
|
||
(
|
||
"file.xls",
|
||
"M",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"renamed": ("work-horus.xls", "file.xls"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {NEW_FILENODE: "new file 100644", BIN_FILENODE: "binary diff hidden"},
|
||
},
|
||
),
|
||
(
|
||
"js/jquery/hashgrid.js",
|
||
"A",
|
||
{
|
||
"added": 340,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100755",
|
||
"ops": {NEW_FILENODE: "new file 100755"},
|
||
},
|
||
),
|
||
(
|
||
"index.html",
|
||
"M",
|
||
{
|
||
"added": 3,
|
||
"deleted": 2,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"less/docs.less",
|
||
"M",
|
||
{
|
||
"added": 34,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"less/scaffolding.less",
|
||
"M",
|
||
{
|
||
"added": 1,
|
||
"deleted": 3,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"readme.markdown",
|
||
"M",
|
||
{
|
||
"added": 1,
|
||
"deleted": 10,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"img/baseline-20px.png",
|
||
"D",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {DEL_FILENODE: "deleted file", BIN_FILENODE: "binary diff hidden"},
|
||
},
|
||
),
|
||
(
|
||
"js/global.js",
|
||
"D",
|
||
{
|
||
"added": 0,
|
||
"deleted": 75,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {DEL_FILENODE: "deleted file"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"hg",
|
||
"diff_with_diff_data.diff",
|
||
[
|
||
(
|
||
"vcs/backends/base.py",
|
||
"M",
|
||
{
|
||
"added": 18,
|
||
"deleted": 2,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"vcs/backends/git/repository.py",
|
||
"M",
|
||
{
|
||
"added": 46,
|
||
"deleted": 15,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"vcs/backends/hg.py",
|
||
"M",
|
||
{
|
||
"added": 22,
|
||
"deleted": 3,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"vcs/tests/test_git.py",
|
||
"M",
|
||
{
|
||
"added": 5,
|
||
"deleted": 5,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"vcs/tests/test_repository.py",
|
||
"M",
|
||
{
|
||
"added": 174,
|
||
"deleted": 2,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"hg",
|
||
"hg_diff_copy_file.diff",
|
||
[
|
||
(
|
||
"file2",
|
||
"M",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": True,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"copied": ("file1", "file2"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"copied": ("file2", "file3"),
|
||
"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,
|
||
"old_mode": "100644",
|
||
"new_mode": "100755",
|
||
"copied": ("file3", "file4"),
|
||
"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,
|
||
"old_mode": "100755",
|
||
"new_mode": "100644",
|
||
"copied": ("file4", "file5"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"renamed": ("file_with_ spaces.txt", "file_with_ two spaces.txt"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"renamed": ("file_ with update.txt", "file_changed _.txt"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"copied": ("file_changed_without_spaces.txt", "file_copied_ with spaces.txt"),
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"ops": {
|
||
NEW_FILENODE: "new file 100644",
|
||
},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"svn",
|
||
"svn_diff_binary_add_file.diff",
|
||
[
|
||
(
|
||
"intl.dll",
|
||
"A",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "10644",
|
||
"ops": {
|
||
NEW_FILENODE: "new file 10644",
|
||
# TODO(Marcink): depends on binary detection on svn patches
|
||
# BIN_FILENODE: 'binary diff hidden'
|
||
},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
(
|
||
"svn",
|
||
"svn_diff_multiple_changes.diff",
|
||
[
|
||
(
|
||
"trunk/doc/images/SettingsOverlay.png",
|
||
"M",
|
||
{
|
||
"added": 0,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {
|
||
MOD_FILENODE: "modified file",
|
||
# TODO(Marcink): depends on binary detection on svn patches
|
||
# BIN_FILENODE: 'binary diff hidden'
|
||
},
|
||
},
|
||
),
|
||
(
|
||
"trunk/doc/source/de/tsvn_ch04.xml",
|
||
"M",
|
||
{
|
||
"added": 89,
|
||
"deleted": 34,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/doc/source/en/tsvn_ch04.xml",
|
||
"M",
|
||
{
|
||
"added": 66,
|
||
"deleted": 21,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/Changelog.txt",
|
||
"M",
|
||
{
|
||
"added": 2,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/Resources/TortoiseProcENG.rc",
|
||
"M",
|
||
{
|
||
"added": 19,
|
||
"deleted": 13,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/TortoiseProc/SetOverlayPage.cpp",
|
||
"M",
|
||
{
|
||
"added": 16,
|
||
"deleted": 1,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/TortoiseProc/SetOverlayPage.h",
|
||
"M",
|
||
{
|
||
"added": 3,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/TortoiseProc/resource.h",
|
||
"M",
|
||
{
|
||
"added": 2,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
(
|
||
"trunk/src/TortoiseShell/ShellCache.h",
|
||
"M",
|
||
{
|
||
"added": 50,
|
||
"deleted": 1,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "",
|
||
"ops": {MOD_FILENODE: "modified file"},
|
||
},
|
||
),
|
||
],
|
||
),
|
||
]
|
||
|
||
DIFF_FIXTURES_WITH_CONTENT = [
|
||
(
|
||
"hg",
|
||
"hg_diff_single_file_change_newline.diff",
|
||
[
|
||
(
|
||
"file_b", # filename
|
||
"A", # change
|
||
{ # stats
|
||
"added": 1,
|
||
"deleted": 0,
|
||
"binary": False,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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,
|
||
"old_mode": "",
|
||
"new_mode": "100644",
|
||
"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.mark.parametrize("vcs_type, diff_file, expected_data", DIFF_FIXTURES)
|
||
def test_diff_lib(vcs_type, diff_file, expected_data):
|
||
diff_txt = fixture.load_resource(diff_file)
|
||
diff = diff_class[vcs_type](diff_txt)
|
||
|
||
diff_proc = DiffProcessor(diff, diff_format="newdiff")
|
||
diff_proc_d = diff_proc.prepare()
|
||
data = [(x["filename"], x["operation"], x["stats"]) for x in diff_proc_d]
|
||
assert expected_data == data
|
||
|
||
|
||
@pytest.mark.parametrize("vcs_type, diff_file, expected_data", DIFF_FIXTURES_WITH_CONTENT)
|
||
def test_diff_lib_newlines(vcs_type, diff_file, expected_data):
|
||
diff_txt = fixture.load_resource(diff_file)
|
||
diff = diff_class[vcs_type](diff_txt)
|
||
|
||
diff_proc = DiffProcessor(diff, diff_format="newdiff")
|
||
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
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
"input_str",
|
||
[
|
||
b"",
|
||
b"\n",
|
||
b"\n\n",
|
||
b"First\n+second",
|
||
b"First\n+second\n",
|
||
b"\n\n\n Multi \n\n\n",
|
||
b"\n\n\n Multi beginning",
|
||
b"Multi end \n\n\n",
|
||
b"Multi end",
|
||
b"@@ -0,0 +1 @@\n+test_content \n\n b\n",
|
||
],
|
||
ids=no_newline_id_generator,
|
||
)
|
||
def test_splitlines(input_str):
|
||
result = DiffProcessor.diff_splitter(input_str)
|
||
assert list(result) == input_str.splitlines(True)
|
||
|
||
|
||
def test_diff_over_limit(request):
|
||
diff_limit = 1024
|
||
file_limit = 1024
|
||
|
||
raw_diff = fixture.load_resource("large_diff.diff")
|
||
vcs_diff = GitDiff(raw_diff)
|
||
diff_processor = DiffProcessor(
|
||
vcs_diff, diff_format="newdiff", diff_limit=diff_limit, file_limit=file_limit, show_full_diff=False
|
||
)
|
||
|
||
_parsed = diff_processor.prepare()
|
||
|
||
commit1 = GitCommit(repository=mock.Mock(), raw_id="abcdef12", idx=1)
|
||
commit2 = GitCommit(repository=mock.Mock(), raw_id="abcdef34", idx=2)
|
||
|
||
diffset = DiffSet(
|
||
repo_name="repo_name",
|
||
source_node_getter=lambda *a, **kw: AttributeDict({"commit": commit1}),
|
||
target_node_getter=lambda *a, **kw: AttributeDict({"commit": commit2}),
|
||
)
|
||
|
||
diffset = diffset.render_patchset(_parsed, commit1, commit2)
|
||
|
||
assert len(diffset.files) == 2
|
||
assert diffset.limited_diff is True
|
||
assert diffset.files[0].patch["filename"] == "example.go"
|
||
assert diffset.files[0].limited_diff is True
|
||
|
||
assert diffset.files[1].patch["filename"] == "README.md"
|
||
assert diffset.files[1].limited_diff is False
|