|
|
|
|
|
# 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 mock
|
|
|
import pytest
|
|
|
import lxml.html
|
|
|
|
|
|
from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
|
|
|
from rhodecode.tests import assert_session_flash
|
|
|
from rhodecode.tests.utils import AssertResponse, commit_change
|
|
|
from rhodecode.tests.routes import route_path
|
|
|
|
|
|
|
|
|
@pytest.mark.usefixtures("autologin_user", "app")
|
|
|
class TestCompareView(object):
|
|
|
|
|
|
def test_compare_index_is_reached_at_least_once(self, backend):
|
|
|
repo = backend.repo
|
|
|
self.app.get(
|
|
|
route_path('repo_compare_select', repo_name=repo.repo_name))
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn", reason="Requires pull")
|
|
|
def test_compare_remote_with_different_commit_indexes(self, backend):
|
|
|
# Preparing the following repository structure:
|
|
|
#
|
|
|
# Origin repository has two commits:
|
|
|
#
|
|
|
# 0 1
|
|
|
# A -- D
|
|
|
#
|
|
|
# The fork of it has a few more commits and "D" has a commit index
|
|
|
# which does not exist in origin.
|
|
|
#
|
|
|
# 0 1 2 3 4
|
|
|
# A -- -- -- D -- E
|
|
|
# \- B -- C
|
|
|
#
|
|
|
|
|
|
fork = backend.create_repo()
|
|
|
origin = backend.create_repo()
|
|
|
|
|
|
# prepare fork
|
|
|
commit0 = commit_change(
|
|
|
fork.repo_name, filename=b'file1', content=b'A',
|
|
|
message='A - Initial Commit', vcs_type=backend.alias, parent=None, newfile=True)
|
|
|
|
|
|
commit1 = commit_change(
|
|
|
fork.repo_name, filename=b'file1', content=b'B',
|
|
|
message='B, child of A', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
commit_change( # commit 2
|
|
|
fork.repo_name, filename=b'file1', content=b'C',
|
|
|
message='C, child of B', vcs_type=backend.alias, parent=commit1)
|
|
|
|
|
|
commit3 = commit_change(
|
|
|
fork.repo_name, filename=b'file1', content=b'D',
|
|
|
message='D, child of A', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
commit4 = commit_change(
|
|
|
fork.repo_name, filename=b'file1', content=b'E',
|
|
|
message='E, child of D', vcs_type=backend.alias, parent=commit3)
|
|
|
|
|
|
# prepare origin repository, taking just the history up to D
|
|
|
|
|
|
origin_repo = origin.scm_instance(cache=False)
|
|
|
origin_repo.config.clear_section('hooks')
|
|
|
origin_repo.pull(fork.repo_full_path, commit_ids=[commit3.raw_id])
|
|
|
origin_repo = origin.scm_instance(cache=False) # cache rebuild
|
|
|
|
|
|
# Verify test fixture setup
|
|
|
# This does not work for git
|
|
|
if backend.alias != 'git':
|
|
|
assert 5 == len(fork.scm_instance(cache=False).commit_ids)
|
|
|
assert 2 == len(origin_repo.commit_ids)
|
|
|
|
|
|
# Comparing the revisions
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=origin.repo_name,
|
|
|
source_ref_type="rev", source_ref=commit3.raw_id,
|
|
|
target_ref_type="rev", target_ref=commit4.raw_id,
|
|
|
params=dict(merge='1', target_repo=fork.repo_name)
|
|
|
),
|
|
|
status=200)
|
|
|
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_commits([commit4])
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn", reason="Depends on branch support")
|
|
|
def test_compare_forks_on_branch_extra_commits(self, backend):
|
|
|
repo1 = backend.create_repo()
|
|
|
|
|
|
# commit something !
|
|
|
commit0 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\n',
|
|
|
message='commit1', vcs_type=backend.alias, parent=None,
|
|
|
newfile=True)
|
|
|
|
|
|
# fork this repo
|
|
|
repo2 = backend.create_fork()
|
|
|
|
|
|
# add two extra commit into fork
|
|
|
commit1 = commit_change(
|
|
|
repo2.repo_name, filename=b'file1', content=b'line1\nline2\n',
|
|
|
message='commit2', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
commit2 = commit_change(
|
|
|
repo2.repo_name, filename=b'file1', content=b'line1\nline2\nline3\n',
|
|
|
message='commit3', vcs_type=backend.alias, parent=commit1)
|
|
|
|
|
|
commit_id1 = repo1.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
commit_id2 = repo2.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo1.repo_name,
|
|
|
source_ref_type="branch", source_ref=commit_id2,
|
|
|
target_ref_type="branch", target_ref=commit_id1,
|
|
|
params=dict(merge='1', target_repo=repo2.repo_name)
|
|
|
))
|
|
|
|
|
|
response.mustcontain('%s@%s' % (repo1.repo_name, commit_id2))
|
|
|
response.mustcontain('%s@%s' % (repo2.repo_name, commit_id1))
|
|
|
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 2, 0)
|
|
|
compare_page.contains_commits([commit1, commit2])
|
|
|
|
|
|
anchor = 'a_c-{}-826e8142e6ba'.format(commit0.short_id)
|
|
|
compare_page.contains_file_links_and_anchors([('file1', anchor), ])
|
|
|
|
|
|
# Swap is removed when comparing branches since it's a PR feature and
|
|
|
# it is then a preview mode
|
|
|
compare_page.swap_is_hidden()
|
|
|
compare_page.target_source_are_disabled()
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn", reason="Depends on branch support")
|
|
|
def test_compare_forks_on_branch_extra_commits_origin_has_incoming(self, backend):
|
|
|
repo1 = backend.create_repo()
|
|
|
|
|
|
# commit something !
|
|
|
commit0 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\n',
|
|
|
message='commit1', vcs_type=backend.alias, parent=None,
|
|
|
newfile=True)
|
|
|
|
|
|
# fork this repo
|
|
|
repo2 = backend.create_fork()
|
|
|
|
|
|
# now commit something to origin repo
|
|
|
commit_change(
|
|
|
repo1.repo_name, filename=b'file2', content=b'line1file2\n',
|
|
|
message='commit2', vcs_type=backend.alias, parent=commit0,
|
|
|
newfile=True)
|
|
|
|
|
|
# add two extra commit into fork
|
|
|
commit1 = commit_change(
|
|
|
repo2.repo_name, filename=b'file1', content=b'line1\nline2\n',
|
|
|
message='commit2', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
commit2 = commit_change(
|
|
|
repo2.repo_name, filename=b'file1', content=b'line1\nline2\nline3\n',
|
|
|
message='commit3', vcs_type=backend.alias, parent=commit1)
|
|
|
|
|
|
commit_id1 = repo1.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
commit_id2 = repo2.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo1.repo_name,
|
|
|
source_ref_type="branch", source_ref=commit_id2,
|
|
|
target_ref_type="branch", target_ref=commit_id1,
|
|
|
params=dict(merge='1', target_repo=repo2.repo_name),
|
|
|
))
|
|
|
|
|
|
response.mustcontain(f'{repo1.repo_name}@{commit_id2}')
|
|
|
response.mustcontain(f'{repo2.repo_name}@{commit_id1}')
|
|
|
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 2, 0)
|
|
|
compare_page.contains_commits([commit1, commit2])
|
|
|
anchor = f'a_c-{commit0.short_id}-826e8142e6ba'
|
|
|
compare_page.contains_file_links_and_anchors([('file1', anchor), ])
|
|
|
|
|
|
# Swap is removed when comparing branches since it's a PR feature and
|
|
|
# it is then a preview mode
|
|
|
compare_page.swap_is_hidden()
|
|
|
compare_page.target_source_are_disabled()
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
# TODO(marcink): no svn support for compare two seperate repos
|
|
|
def test_compare_of_unrelated_forks(self, backend):
|
|
|
orig = backend.create_repo(number_of_commits=1)
|
|
|
fork = backend.create_repo(number_of_commits=1)
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=orig.repo_name,
|
|
|
source_ref_type="rev", source_ref="tip",
|
|
|
target_ref_type="rev", target_ref="tip",
|
|
|
params=dict(merge='1', target_repo=fork.repo_name),
|
|
|
),
|
|
|
status=302)
|
|
|
response = response.follow()
|
|
|
response.mustcontain("Repositories unrelated.")
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
def test_compare_cherry_pick_commits_from_bottom(self, backend):
|
|
|
|
|
|
# repo1:
|
|
|
# commit0:
|
|
|
# commit1:
|
|
|
# repo1-fork- in which we will cherry pick bottom commits
|
|
|
# commit0:
|
|
|
# commit1:
|
|
|
# commit2: x
|
|
|
# commit3: x
|
|
|
# commit4: x
|
|
|
# commit5:
|
|
|
# make repo1, and commit1+commit2
|
|
|
|
|
|
repo1 = backend.create_repo()
|
|
|
|
|
|
# commit something !
|
|
|
commit0 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\n',
|
|
|
message='commit1', vcs_type=backend.alias, parent=None,
|
|
|
newfile=True)
|
|
|
commit1 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\n',
|
|
|
message='commit2', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
# fork this repo
|
|
|
repo2 = backend.create_fork()
|
|
|
|
|
|
# now make commit3-6
|
|
|
commit2 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\nline3\n',
|
|
|
message='commit3', vcs_type=backend.alias, parent=commit1)
|
|
|
commit3 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1',content=b'line1\nline2\nline3\nline4\n',
|
|
|
message='commit4', vcs_type=backend.alias, parent=commit2)
|
|
|
commit4 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\nline3\nline4\nline5\n',
|
|
|
message='commit5', vcs_type=backend.alias, parent=commit3)
|
|
|
commit_change( # commit 5
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\nline3\nline4\nline5\nline6\n',
|
|
|
message='commit6', vcs_type=backend.alias, parent=commit4)
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo2.repo_name,
|
|
|
# parent of commit2, in target repo2
|
|
|
source_ref_type="rev", source_ref=commit1.raw_id,
|
|
|
target_ref_type="rev", target_ref=commit4.raw_id,
|
|
|
params=dict(merge='1', target_repo=repo1.repo_name),
|
|
|
))
|
|
|
response.mustcontain('%s@%s' % (repo2.repo_name, commit1.short_id))
|
|
|
response.mustcontain('%s@%s' % (repo1.repo_name, commit4.short_id))
|
|
|
|
|
|
# files
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 3, 0)
|
|
|
compare_page.contains_commits([commit2, commit3, commit4])
|
|
|
anchor = 'a_c-{}-826e8142e6ba'.format(commit1.short_id)
|
|
|
compare_page.contains_file_links_and_anchors([('file1', anchor),])
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
def test_compare_cherry_pick_commits_from_top(self, backend):
|
|
|
# repo1:
|
|
|
# commit0:
|
|
|
# commit1:
|
|
|
# repo1-fork- in which we will cherry pick bottom commits
|
|
|
# commit0:
|
|
|
# commit1:
|
|
|
# commit2:
|
|
|
# commit3: x
|
|
|
# commit4: x
|
|
|
# commit5: x
|
|
|
|
|
|
# make repo1, and commit1+commit2
|
|
|
repo1 = backend.create_repo()
|
|
|
|
|
|
# commit something !
|
|
|
commit0 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\n',
|
|
|
message='commit1', vcs_type=backend.alias, parent=None,
|
|
|
newfile=True)
|
|
|
commit1 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\n',
|
|
|
message='commit2', vcs_type=backend.alias, parent=commit0)
|
|
|
|
|
|
# fork this repo
|
|
|
backend.create_fork()
|
|
|
|
|
|
# now make commit3-6
|
|
|
commit2 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1', content=b'line1\nline2\nline3\n',
|
|
|
message='commit3', vcs_type=backend.alias, parent=commit1)
|
|
|
commit3 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1',
|
|
|
content=b'line1\nline2\nline3\nline4\n', message='commit4',
|
|
|
vcs_type=backend.alias, parent=commit2)
|
|
|
commit4 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1',
|
|
|
content=b'line1\nline2\nline3\nline4\nline5\n', message='commit5',
|
|
|
vcs_type=backend.alias, parent=commit3)
|
|
|
commit5 = commit_change(
|
|
|
repo1.repo_name, filename=b'file1',
|
|
|
content=b'line1\nline2\nline3\nline4\nline5\nline6\n',
|
|
|
message='commit6', vcs_type=backend.alias, parent=commit4)
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo1.repo_name,
|
|
|
# parent of commit3, not in source repo2
|
|
|
source_ref_type="rev", source_ref=commit2.raw_id,
|
|
|
target_ref_type="rev", target_ref=commit5.raw_id,
|
|
|
params=dict(merge='1'),))
|
|
|
|
|
|
response.mustcontain('%s@%s' % (repo1.repo_name, commit2.short_id))
|
|
|
response.mustcontain('%s@%s' % (repo1.repo_name, commit5.short_id))
|
|
|
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 3, 0)
|
|
|
compare_page.contains_commits([commit3, commit4, commit5])
|
|
|
|
|
|
# files
|
|
|
anchor = 'a_c-{}-826e8142e6ba'.format(commit2.short_id)
|
|
|
compare_page.contains_file_links_and_anchors([('file1', anchor),])
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
def test_compare_remote_branches(self, backend):
|
|
|
repo1 = backend.repo
|
|
|
repo2 = backend.create_fork()
|
|
|
|
|
|
commit_id1 = repo1.get_commit(commit_idx=3).raw_id
|
|
|
commit_id1_short = repo1.get_commit(commit_idx=3).short_id
|
|
|
commit_id2 = repo1.get_commit(commit_idx=6).raw_id
|
|
|
commit_id2_short = repo1.get_commit(commit_idx=6).short_id
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo1.repo_name,
|
|
|
source_ref_type="rev", source_ref=commit_id1,
|
|
|
target_ref_type="rev", target_ref=commit_id2,
|
|
|
params=dict(merge='1', target_repo=repo2.repo_name),
|
|
|
))
|
|
|
|
|
|
response.mustcontain('%s@%s' % (repo1.repo_name, commit_id1))
|
|
|
response.mustcontain('%s@%s' % (repo2.repo_name, commit_id2))
|
|
|
|
|
|
compare_page = ComparePage(response)
|
|
|
|
|
|
# outgoing commits between those commits
|
|
|
compare_page.contains_commits(
|
|
|
[repo2.get_commit(commit_idx=x) for x in [4, 5, 6]])
|
|
|
|
|
|
# files
|
|
|
compare_page.contains_file_links_and_anchors([
|
|
|
('vcs/backends/hg.py', 'a_c-{}-9c390eb52cd6'.format(commit_id2_short)),
|
|
|
('vcs/backends/__init__.py', 'a_c-{}-41b41c1f2796'.format(commit_id1_short)),
|
|
|
('vcs/backends/base.py', 'a_c-{}-2f574d260608'.format(commit_id1_short)),
|
|
|
])
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
def test_source_repo_new_commits_after_forking_simple_diff(self, backend):
|
|
|
repo1 = backend.create_repo()
|
|
|
r1_name = repo1.repo_name
|
|
|
|
|
|
commit0 = commit_change(
|
|
|
repo=r1_name, filename=b'file1',
|
|
|
content=b'line1', message='commit1', vcs_type=backend.alias,
|
|
|
newfile=True)
|
|
|
assert repo1.scm_instance().commit_ids == [commit0.raw_id]
|
|
|
|
|
|
# fork the repo1
|
|
|
repo2 = backend.create_fork()
|
|
|
assert repo2.scm_instance().commit_ids == [commit0.raw_id]
|
|
|
|
|
|
self.r2_id = repo2.repo_id
|
|
|
r2_name = repo2.repo_name
|
|
|
|
|
|
commit1 = commit_change(
|
|
|
repo=r2_name, filename=b'file1-fork',
|
|
|
content=b'file1-line1-from-fork', message='commit1-fork',
|
|
|
vcs_type=backend.alias, parent=repo2.scm_instance()[-1],
|
|
|
newfile=True)
|
|
|
|
|
|
commit2 = commit_change(
|
|
|
repo=r2_name, filename=b'file2-fork',
|
|
|
content=b'file2-line1-from-fork', message='commit2-fork',
|
|
|
vcs_type=backend.alias, parent=commit1,
|
|
|
newfile=True)
|
|
|
|
|
|
commit_change( # commit 3
|
|
|
repo=r2_name, filename=b'file3-fork',
|
|
|
content=b'file3-line1-from-fork', message='commit3-fork',
|
|
|
vcs_type=backend.alias, parent=commit2, newfile=True)
|
|
|
|
|
|
# compare !
|
|
|
commit_id1 = repo1.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
commit_id2 = repo2.scm_instance().DEFAULT_BRANCH_NAME
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=r2_name,
|
|
|
source_ref_type="branch", source_ref=commit_id1,
|
|
|
target_ref_type="branch", target_ref=commit_id2,
|
|
|
params=dict(merge='1', target_repo=r1_name),
|
|
|
))
|
|
|
|
|
|
response.mustcontain('%s@%s' % (r2_name, commit_id1))
|
|
|
response.mustcontain('%s@%s' % (r1_name, commit_id2))
|
|
|
response.mustcontain('No files')
|
|
|
response.mustcontain('No commits in this compare')
|
|
|
|
|
|
commit0 = commit_change(
|
|
|
repo=r1_name, filename=b'file2',
|
|
|
content=b'line1-added-after-fork', message='commit2-parent',
|
|
|
vcs_type=backend.alias, parent=None, newfile=True)
|
|
|
|
|
|
# compare !
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=r2_name,
|
|
|
source_ref_type="branch", source_ref=commit_id1,
|
|
|
target_ref_type="branch", target_ref=commit_id2,
|
|
|
params=dict(merge='1', target_repo=r1_name),
|
|
|
))
|
|
|
|
|
|
response.mustcontain('%s@%s' % (r2_name, commit_id1))
|
|
|
response.mustcontain('%s@%s' % (r1_name, commit_id2))
|
|
|
|
|
|
response.mustcontain("""commit2-parent""")
|
|
|
response.mustcontain("""line1-added-after-fork""")
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 1, 0)
|
|
|
|
|
|
@pytest.mark.xfail_backends("svn")
|
|
|
def test_compare_commits(self, backend, xhr_header):
|
|
|
commit0 = backend.repo.get_commit(commit_idx=0)
|
|
|
commit1 = backend.repo.get_commit(commit_idx=1)
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=backend.repo_name,
|
|
|
source_ref_type="rev", source_ref=commit0.raw_id,
|
|
|
target_ref_type="rev", target_ref=commit1.raw_id,
|
|
|
params=dict(merge='1')
|
|
|
),
|
|
|
extra_environ=xhr_header, )
|
|
|
|
|
|
# outgoing commits between those commits
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_commits(commits=[commit1])
|
|
|
|
|
|
def test_errors_when_comparing_unknown_source_repo(self, backend):
|
|
|
repo = backend.repo
|
|
|
|
|
|
self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name='badrepo',
|
|
|
source_ref_type="rev", source_ref='tip',
|
|
|
target_ref_type="rev", target_ref='tip',
|
|
|
params=dict(merge='1', target_repo=repo.repo_name)
|
|
|
),
|
|
|
status=404)
|
|
|
|
|
|
def test_errors_when_comparing_unknown_target_repo(self, backend):
|
|
|
repo = backend.repo
|
|
|
badrepo = 'badrepo'
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo.repo_name,
|
|
|
source_ref_type="rev", source_ref='tip',
|
|
|
target_ref_type="rev", target_ref='tip',
|
|
|
params=dict(merge='1', target_repo=badrepo),
|
|
|
),
|
|
|
status=302)
|
|
|
redirected = response.follow()
|
|
|
redirected.mustcontain(
|
|
|
'Could not find the target repo: `{}`'.format(badrepo))
|
|
|
|
|
|
def test_compare_not_in_preview_mode(self, backend_stub):
|
|
|
commit0 = backend_stub.repo.get_commit(commit_idx=0)
|
|
|
commit1 = backend_stub.repo.get_commit(commit_idx=1)
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=backend_stub.repo_name,
|
|
|
source_ref_type="rev", source_ref=commit0.raw_id,
|
|
|
target_ref_type="rev", target_ref=commit1.raw_id,
|
|
|
))
|
|
|
|
|
|
# outgoing commits between those commits
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.swap_is_visible()
|
|
|
compare_page.target_source_are_enabled()
|
|
|
|
|
|
def test_compare_of_fork_with_largefiles(self, backend_hg, settings_util):
|
|
|
orig = backend_hg.create_repo(number_of_commits=1)
|
|
|
fork = backend_hg.create_fork()
|
|
|
|
|
|
settings_util.create_repo_rhodecode_ui(
|
|
|
orig, 'extensions', value='', key='largefiles', active=False)
|
|
|
settings_util.create_repo_rhodecode_ui(
|
|
|
fork, 'extensions', value='', key='largefiles', active=True)
|
|
|
|
|
|
compare_module = ('rhodecode.lib.vcs.backends.hg.repository.'
|
|
|
'MercurialRepository.compare')
|
|
|
with mock.patch(compare_module) as compare_mock:
|
|
|
compare_mock.side_effect = RepositoryRequirementError()
|
|
|
|
|
|
response = self.app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=orig.repo_name,
|
|
|
source_ref_type="rev", source_ref="tip",
|
|
|
target_ref_type="rev", target_ref="tip",
|
|
|
params=dict(merge='1', target_repo=fork.repo_name),
|
|
|
),
|
|
|
status=302)
|
|
|
|
|
|
assert_session_flash(
|
|
|
response,
|
|
|
'Could not compare repos with different large file settings')
|
|
|
|
|
|
|
|
|
@pytest.mark.usefixtures("autologin_user")
|
|
|
class TestCompareControllerSvn(object):
|
|
|
|
|
|
def test_supports_references_with_path(self, app, backend_svn):
|
|
|
repo = backend_svn['svn-simple-layout']
|
|
|
commit_id = repo.get_commit(commit_idx=-1).raw_id
|
|
|
response = app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo.repo_name,
|
|
|
source_ref_type="tag",
|
|
|
source_ref="%s@%s" % ('tags/v0.1', commit_id),
|
|
|
target_ref_type="tag",
|
|
|
target_ref="%s@%s" % ('tags/v0.2', commit_id),
|
|
|
params=dict(merge='1'),
|
|
|
),
|
|
|
status=200)
|
|
|
|
|
|
# Expecting no commits, since both paths are at the same revision
|
|
|
response.mustcontain('No commits in this compare')
|
|
|
|
|
|
# Should find only one file changed when comparing those two tags
|
|
|
response.mustcontain('example.py')
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 5, 1)
|
|
|
|
|
|
def test_shows_commits_if_different_ids(self, app, backend_svn):
|
|
|
repo = backend_svn['svn-simple-layout']
|
|
|
source_id = repo.get_commit(commit_idx=-6).raw_id
|
|
|
target_id = repo.get_commit(commit_idx=-1).raw_id
|
|
|
response = app.get(
|
|
|
route_path('repo_compare',
|
|
|
repo_name=repo.repo_name,
|
|
|
source_ref_type="tag",
|
|
|
source_ref="%s@%s" % ('tags/v0.1', source_id),
|
|
|
target_ref_type="tag",
|
|
|
target_ref="%s@%s" % ('tags/v0.2', target_id),
|
|
|
params=dict(merge='1')
|
|
|
),
|
|
|
status=200)
|
|
|
|
|
|
# It should show commits
|
|
|
assert 'No commits in this compare' not in response.text
|
|
|
|
|
|
# Should find only one file changed when comparing those two tags
|
|
|
response.mustcontain('example.py')
|
|
|
compare_page = ComparePage(response)
|
|
|
compare_page.contains_change_summary(1, 5, 1)
|
|
|
|
|
|
|
|
|
class ComparePage(AssertResponse):
|
|
|
"""
|
|
|
Abstracts the page template from the tests
|
|
|
"""
|
|
|
|
|
|
def contains_file_links_and_anchors(self, files):
|
|
|
doc = lxml.html.fromstring(self.response.body)
|
|
|
for filename, file_id in files:
|
|
|
self.contains_one_anchor(file_id)
|
|
|
diffblock = doc.cssselect('[data-f-path="%s"]' % filename)
|
|
|
assert len(diffblock) == 2
|
|
|
for lnk in diffblock[0].cssselect('a'):
|
|
|
if 'permalink' in lnk.text:
|
|
|
assert '#{}'.format(file_id) in lnk.attrib['href']
|
|
|
break
|
|
|
else:
|
|
|
pytest.fail('Unable to find permalink')
|
|
|
|
|
|
def contains_change_summary(self, files_changed, inserted, deleted):
|
|
|
template = (
|
|
|
'{files_changed} file{plural} changed: '
|
|
|
'<span class="op-added">{inserted} inserted</span>, <span class="op-deleted">{deleted} deleted</span>')
|
|
|
self.response.mustcontain(template.format(
|
|
|
files_changed=files_changed,
|
|
|
plural="s" if files_changed > 1 else "",
|
|
|
inserted=inserted,
|
|
|
deleted=deleted))
|
|
|
|
|
|
def contains_commits(self, commits, ancestors=None):
|
|
|
response = self.response
|
|
|
|
|
|
for commit in commits:
|
|
|
# Expecting to see the commit message in an element which
|
|
|
# has the ID "c-{commit.raw_id}"
|
|
|
self.element_contains('#c-' + commit.raw_id, commit.message)
|
|
|
self.contains_one_link(
|
|
|
'r%s:%s' % (commit.idx, commit.short_id),
|
|
|
self._commit_url(commit))
|
|
|
|
|
|
if ancestors:
|
|
|
response.mustcontain('Ancestor')
|
|
|
for ancestor in ancestors:
|
|
|
self.contains_one_link(
|
|
|
ancestor.short_id, self._commit_url(ancestor))
|
|
|
|
|
|
def _commit_url(self, commit):
|
|
|
return '/%s/changeset/%s' % (commit.repository.name, commit.raw_id)
|
|
|
|
|
|
def swap_is_hidden(self):
|
|
|
assert '<a id="btn-swap"' not in self.response.text
|
|
|
|
|
|
def swap_is_visible(self):
|
|
|
assert '<a id="btn-swap"' in self.response.text
|
|
|
|
|
|
def target_source_are_disabled(self):
|
|
|
response = self.response
|
|
|
response.mustcontain("var enable_fields = false;")
|
|
|
response.mustcontain('.select2("enable", enable_fields)')
|
|
|
|
|
|
def target_source_are_enabled(self):
|
|
|
response = self.response
|
|
|
response.mustcontain("var enable_fields = true;")
|
|
|
|