|
|
|
|
|
# Copyright (C) 2010-2023 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 os
|
|
|
|
|
|
import mock
|
|
|
import pytest
|
|
|
|
|
|
from rhodecode.lib.str_utils import safe_bytes
|
|
|
from rhodecode.tests import SVN_REPO, TEST_DIR, TESTS_TMP_PATH
|
|
|
from rhodecode.lib.vcs.backends.svn.repository import SubversionRepository
|
|
|
from rhodecode.lib.vcs.conf import settings
|
|
|
from rhodecode.lib.vcs.exceptions import VCSError
|
|
|
|
|
|
|
|
|
pytestmark = [
|
|
|
pytest.mark.backends("svn"),
|
|
|
pytest.mark.usefixtures("baseapp"),
|
|
|
]
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
def repo(baseapp):
|
|
|
repo = SubversionRepository(os.path.join(TESTS_TMP_PATH, SVN_REPO))
|
|
|
return repo
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
def head(repo):
|
|
|
return repo.get_commit()
|
|
|
|
|
|
|
|
|
def test_init_fails_if_path_does_not_exist():
|
|
|
path = os.path.join(TEST_DIR, 'i-do-not-exist')
|
|
|
with pytest.raises(VCSError):
|
|
|
SubversionRepository(path)
|
|
|
|
|
|
|
|
|
def test_init_fails_if_path_is_not_a_valid_repository(tmpdir):
|
|
|
path = str(tmpdir.mkdir('unicode ä'))
|
|
|
with pytest.raises(VCSError):
|
|
|
SubversionRepository(path)
|
|
|
|
|
|
|
|
|
def test_repo_clone(vcsbackend, reposerver):
|
|
|
source = vcsbackend.create_repo(number_of_commits=3)
|
|
|
reposerver.serve(source)
|
|
|
repo = SubversionRepository(
|
|
|
vcsbackend.new_repo_path(),
|
|
|
create=True,
|
|
|
src_url=reposerver.url)
|
|
|
|
|
|
assert source.commit_ids == repo.commit_ids
|
|
|
assert source[0].message == repo[0].message
|
|
|
|
|
|
|
|
|
def test_latest_commit(head):
|
|
|
assert head.raw_id == '393'
|
|
|
|
|
|
|
|
|
def test_commit_description(head):
|
|
|
assert head.message == """Added a symlink"""
|
|
|
|
|
|
|
|
|
def test_commit_author(head):
|
|
|
assert head.author == 'marcin'
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("filename, content, mime_type", [
|
|
|
(b'test.txt', b'Text content\n', None),
|
|
|
(b'test.bin', b'\0 binary \0', 'application/octet-stream'),
|
|
|
], ids=['text', 'binary'])
|
|
|
def test_sets_mime_type_correctly(vcsbackend, filename, content, mime_type):
|
|
|
repo = vcsbackend.create_repo()
|
|
|
vcsbackend.ensure_file(filename, content)
|
|
|
file_properties = repo._remote.node_properties(filename, 1)
|
|
|
assert file_properties.get('svn:mime-type') == mime_type
|
|
|
|
|
|
|
|
|
def test_slice_access(repo):
|
|
|
page_size = 5
|
|
|
page = 0
|
|
|
start = page * page_size
|
|
|
end = start + page_size - 1
|
|
|
|
|
|
commits = list(repo[start:end])
|
|
|
assert [commit.raw_id for commit in commits] == ['1', '2', '3', '4']
|
|
|
|
|
|
|
|
|
def test_walk_changelog_page(repo):
|
|
|
page_size = 5
|
|
|
page = 0
|
|
|
start = page * page_size
|
|
|
end = start + page_size - 1
|
|
|
|
|
|
commits = list(repo[start:end])
|
|
|
changelog = [
|
|
|
'r%s, %s, %s' % (c.raw_id, c.author, c.message) for c in commits]
|
|
|
|
|
|
expexted_messages = [
|
|
|
'r1, marcin, initial import',
|
|
|
'r2, marcin, hg ignore',
|
|
|
'r3, marcin, Pip standards refactor',
|
|
|
'r4, marcin, Base repository few new functions added']
|
|
|
assert changelog == expexted_messages
|
|
|
|
|
|
|
|
|
def test_read_full_file_tree(head):
|
|
|
for topnode, dirs, files in head.walk():
|
|
|
for f in files:
|
|
|
len(f.content)
|
|
|
|
|
|
|
|
|
def test_topnode_files_attribute(head):
|
|
|
topnode = head.get_node('')
|
|
|
topnode.files
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("filename, content, branch, mime_type", [
|
|
|
('branches/plain/test.txt', b'Text content\n', 'plain', None),
|
|
|
('branches/uniçö∂e/test.bin', b'\0 binary \0', 'uniçö∂e', 'application/octet-stream'),
|
|
|
], ids=['text', 'binary'])
|
|
|
def test_unicode_refs(vcsbackend, filename, content, branch, mime_type):
|
|
|
filename = safe_bytes(filename)
|
|
|
repo = vcsbackend.create_repo()
|
|
|
vcsbackend.ensure_file(filename, content)
|
|
|
with mock.patch(("rhodecode.lib.vcs.backends.svn.repository"
|
|
|
".SubversionRepository._patterns_from_section"),
|
|
|
return_value=['branches/*']):
|
|
|
assert f'branches/{branch}' in repo.branches
|
|
|
|
|
|
|
|
|
def test_compatible_version(monkeypatch, vcsbackend):
|
|
|
monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'pre-1.8-compatible')
|
|
|
path = vcsbackend.new_repo_path()
|
|
|
SubversionRepository(path, create=True)
|
|
|
with open(f'{path}/db/format') as f:
|
|
|
first_line = f.readline().strip()
|
|
|
assert first_line == '4'
|
|
|
|
|
|
|
|
|
def test_invalid_compatible_version(monkeypatch, vcsbackend):
|
|
|
monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'i-am-an-invalid-setting')
|
|
|
path = vcsbackend.new_repo_path()
|
|
|
with pytest.raises(Exception):
|
|
|
SubversionRepository(path, create=True)
|
|
|
|
|
|
|
|
|
class TestSVNCommit(object):
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
def prepare(self, repo):
|
|
|
self.repo = repo
|
|
|
|
|
|
def test_file_history_from_commits(self):
|
|
|
node = self.repo[10].get_node('setup.py')
|
|
|
commit_ids = [commit.raw_id for commit in node.history]
|
|
|
assert ['8'] == commit_ids
|
|
|
|
|
|
node = self.repo[20].get_node('setup.py')
|
|
|
node_ids = [commit.raw_id for commit in node.history]
|
|
|
assert ['18',
|
|
|
'8'] == node_ids
|
|
|
|
|
|
# special case we check history from commit that has this particular
|
|
|
# file changed this means we check if it's included as well
|
|
|
node = self.repo.get_commit('18').get_node('setup.py')
|
|
|
node_ids = [commit.raw_id for commit in node.history]
|
|
|
assert ['18',
|
|
|
'8'] == node_ids
|
|
|
|
|
|
def test_repo_files_content_type(self):
|
|
|
test_commit = self.repo.get_commit(commit_idx=100)
|
|
|
for node in test_commit.get_node('/'):
|
|
|
if node.is_file():
|
|
|
assert type(node.content) == bytes
|
|
|
assert type(node.str_content) == str
|
|
|
|