diff --git a/rhodecode/apps/repository/tests/test_repo_compare.py b/rhodecode/apps/repository/tests/test_repo_compare.py --- a/rhodecode/apps/repository/tests/test_repo_compare.py +++ b/rhodecode/apps/repository/tests/test_repo_compare.py @@ -94,6 +94,7 @@ class TestCompareView(object): 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 @@ -162,8 +163,7 @@ class TestCompareView(object): 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_incomming( - self, backend): + def test_compare_forks_on_branch_extra_commits_origin_has_incomming(self, backend): repo1 = backend.create_repo() # commit something ! diff --git a/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py b/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py --- a/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py +++ b/rhodecode/apps/repository/tests/test_repo_compare_on_single_file.py @@ -21,6 +21,7 @@ import pytest from rhodecode.lib.vcs import nodes +from rhodecode.lib.vcs.backends.base import EmptyCommit from rhodecode.tests.fixture import Fixture from rhodecode.tests.utils import commit_change @@ -43,70 +44,7 @@ def route_path(name, params=None, **kwar @pytest.mark.usefixtures("autologin_user", "app") class TestSideBySideDiff(object): - def test_diff_side_by_side(self, app, backend, backend_stub): - f_path = 'test_sidebyside_file.py' - commit1_content = 'content-25d7e49c18b159446c\n' - commit2_content = 'content-603d6c72c46d953420\n' - repo = backend.create_repo() - - commit1 = commit_change( - repo.repo_name, filename=f_path, content=commit1_content, - message='A', vcs_type=backend.alias, parent=None, newfile=True) - - commit2 = commit_change( - repo.repo_name, filename=f_path, content=commit2_content, - message='B, child of A', vcs_type=backend.alias, parent=commit1) - - response = self.app.get(route_path( - 'repo_compare', - repo_name=repo.repo_name, - source_ref_type='rev', - source_ref=commit1.raw_id, - target_ref_type='rev', - target_ref=commit2.raw_id, - params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') - )) - - response.mustcontain('Expand 1 commit') - response.mustcontain('1 file changed') - - response.mustcontain( - 'r%s:%s...r%s:%s' % ( - commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) - - response.mustcontain('{}'.format(f_path)) - - def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub): - commits = [ - {'message': 'First commit'}, - {'message': 'Commit with binary', - 'added': [nodes.FileNode('file.empty', content='')]}, - ] - f_path = 'file.empty' - repo = backend.create_repo(commits=commits) - commit1 = repo.get_commit(commit_idx=0) - commit2 = repo.get_commit(commit_idx=1) - - response = self.app.get(route_path( - 'repo_compare', - repo_name=repo.repo_name, - source_ref_type='rev', - source_ref=commit1.raw_id, - target_ref_type='rev', - target_ref=commit2.raw_id, - params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') - )) - - response.mustcontain('Expand 1 commit') - response.mustcontain('1 file changed') - - response.mustcontain( - 'r%s:%s...r%s:%s' % ( - commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) - - response.mustcontain('{}'.format(f_path)) - - def test_diff_sidebyside_two_commits(self, app, backend): + def test_diff_sidebyside_single_commit(self, app, backend): commit_id_range = { 'hg': { 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067', @@ -141,26 +79,164 @@ class TestSideBySideDiff(object): params=dict(target_repo=backend.repo_name, diffmode='sidebyside') )) + response.mustcontain(file_changes) response.mustcontain('Expand 1 commit') - response.mustcontain(file_changes) - def test_diff_sidebyside_two_commits_single_file(self, app, backend): + def test_diff_sidebyside_two_commits(self, app, backend): commit_id_range = { 'hg': { - 'commits': ['25d7e49c18b159446cadfa506a5cf8ad1cb04067', + 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7', '603d6c72c46d953420c89d36372f08d9f305f5dd'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1165 inserted, 308 deleted' }, 'git': { - 'commits': ['6fc9270775aaf5544c1deb014f4ddd60c952fcbb', + 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13', '03fa803d7e9fb14daa9a3089e0d1494eda75d986'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1165 inserted, 308 deleted' }, 'svn': { - 'commits': ['336', + 'commits': ['335', '337'], - 'changes': '1 file changed: 1 inserted, 1 deleted' + 'changes': '32 files changed: 1179 inserted, 310 deleted' + }, + } + + commit_info = commit_id_range[backend.alias] + commit2, commit1 = commit_info['commits'] + file_changes = commit_info['changes'] + + response = self.app.get(route_path( + 'repo_compare', + repo_name=backend.repo_name, + source_ref_type='rev', + source_ref=commit2, + target_repo=backend.repo_name, + target_ref_type='rev', + target_ref=commit1, + params=dict(target_repo=backend.repo_name, diffmode='sidebyside') + )) + + response.mustcontain(file_changes) + response.mustcontain('Expand 2 commits') + + @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)') + def test_diff_side_by_side_from_0_commit(self, app, backend, backend_stub): + f_path = 'test_sidebyside_file.py' + commit1_content = 'content-25d7e49c18b159446c\n' + commit2_content = 'content-603d6c72c46d953420\n' + repo = backend.create_repo() + + commit1 = commit_change( + repo.repo_name, filename=f_path, content=commit1_content, + message='A', vcs_type=backend.alias, parent=None, newfile=True) + + commit2 = commit_change( + repo.repo_name, filename=f_path, content=commit2_content, + message='B, child of A', vcs_type=backend.alias, parent=commit1) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=EmptyCommit().raw_id, + target_ref_type='rev', + target_ref=commit2.raw_id, + params=dict(diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('123 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) + + response.mustcontain('{}'.format(f_path)) + + @pytest.mark.xfail(reason='GIT does not handle empty commit compare correct (missing 1 commit)') + def test_diff_side_by_side_from_0_commit_with_file_filter(self, app, backend, backend_stub): + f_path = 'test_sidebyside_file.py' + commit1_content = 'content-25d7e49c18b159446c\n' + commit2_content = 'content-603d6c72c46d953420\n' + repo = backend.create_repo() + + commit1 = commit_change( + repo.repo_name, filename=f_path, content=commit1_content, + message='A', vcs_type=backend.alias, parent=None, newfile=True) + + commit2 = commit_change( + repo.repo_name, filename=f_path, content=commit2_content, + message='B, child of A', vcs_type=backend.alias, parent=commit1) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=EmptyCommit().raw_id, + target_ref_type='rev', + target_ref=commit2.raw_id, + params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('1 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit1.idx, commit1.short_id, commit2.idx, commit2.short_id)) + + response.mustcontain('{}'.format(f_path)) + + def test_diff_side_by_side_with_empty_file(self, app, backend, backend_stub): + commits = [ + {'message': 'First commit'}, + {'message': 'Second commit'}, + {'message': 'Commit with binary', + 'added': [nodes.FileNode('file.empty', content='')]}, + ] + f_path = 'file.empty' + repo = backend.create_repo(commits=commits) + commit1 = repo.get_commit(commit_idx=0) + commit2 = repo.get_commit(commit_idx=1) + commit3 = repo.get_commit(commit_idx=2) + + response = self.app.get(route_path( + 'repo_compare', + repo_name=repo.repo_name, + source_ref_type='rev', + source_ref=commit1.raw_id, + target_ref_type='rev', + target_ref=commit3.raw_id, + params=dict(f_path=f_path, target_repo=repo.repo_name, diffmode='sidebyside') + )) + + response.mustcontain('Expand 2 commits') + response.mustcontain('1 file changed') + + response.mustcontain( + 'r%s:%s...r%s:%s' % ( + commit2.idx, commit2.short_id, commit3.idx, commit3.short_id)) + + response.mustcontain('{}'.format(f_path)) + + def test_diff_sidebyside_two_commits_with_file_filter(self, app, backend): + commit_id_range = { + 'hg': { + 'commits': ['4fdd71e9427417b2e904e0464c634fdee85ec5a7', + '603d6c72c46d953420c89d36372f08d9f305f5dd'], + 'changes': '1 file changed: 3 inserted, 3 deleted' + }, + 'git': { + 'commits': ['f5fbf9cfd5f1f1be146f6d3b38bcd791a7480c13', + '03fa803d7e9fb14daa9a3089e0d1494eda75d986'], + 'changes': '1 file changed: 3 inserted, 3 deleted' + }, + + 'svn': { + 'commits': ['335', + '337'], + 'changes': '1 file changed: 3 inserted, 3 deleted' }, } f_path = 'docs/conf.py' @@ -179,5 +255,5 @@ class TestSideBySideDiff(object): params=dict(f_path=f_path, target_repo=backend.repo_name, diffmode='sidebyside') )) - response.mustcontain('Expand 1 commit') + response.mustcontain('Expand 2 commits') response.mustcontain(file_changes) diff --git a/rhodecode/apps/repository/views/repo_compare.py b/rhodecode/apps/repository/views/repo_compare.py --- a/rhodecode/apps/repository/views/repo_compare.py +++ b/rhodecode/apps/repository/views/repo_compare.py @@ -214,29 +214,23 @@ class RepoCompareView(RepoAppView): pre_load = ["author", "branch", "date", "message"] c.ancestor = None - if c.file_path: - if source_commit == target_commit: - c.commit_ranges = [] - else: - c.commit_ranges = [source_commit, target_commit] - else: - try: - c.commit_ranges = source_scm.compare( - source_commit.raw_id, target_commit.raw_id, - target_scm, merge, pre_load=pre_load) - if merge: - c.ancestor = source_scm.get_common_ancestor( - source_commit.raw_id, target_commit.raw_id, target_scm) - except RepositoryRequirementError: - msg = _('Could not compare repos with different ' - 'large file settings') - log.error(msg) - if partial: - return Response(msg) - h.flash(msg, category='error') - raise HTTPFound( - h.route_path('repo_compare_select', - repo_name=self.db_repo_name)) + try: + c.commit_ranges = source_scm.compare( + source_commit.raw_id, target_commit.raw_id, + target_scm, merge, pre_load=pre_load) or [] + if merge: + c.ancestor = source_scm.get_common_ancestor( + source_commit.raw_id, target_commit.raw_id, target_scm) + except RepositoryRequirementError: + msg = _('Could not compare repos with different ' + 'large file settings') + log.error(msg) + if partial: + return Response(msg) + h.flash(msg, category='error') + raise HTTPFound( + h.route_path('repo_compare_select', + repo_name=self.db_repo_name)) c.statuses = self.db_repo.statuses( [x.raw_id for x in c.commit_ranges]) diff --git a/rhodecode/lib/vcs/backends/base.py b/rhodecode/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/rhodecode/lib/vcs/backends/base.py @@ -55,6 +55,7 @@ log = logging.getLogger(__name__) FILEMODE_DEFAULT = 0o100644 FILEMODE_EXECUTABLE = 0o100755 +EMPTY_COMMIT_ID = '0' * 40 Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id')) @@ -1569,7 +1570,7 @@ class EmptyCommit(BaseCommit): """ def __init__( - self, commit_id='0' * 40, repo=None, alias=None, idx=-1, + self, commit_id=EMPTY_COMMIT_ID, repo=None, alias=None, idx=-1, message='', author='', date=None): self._empty_commit_id = commit_id # TODO: johbo: Solve idx parameter, default value does not make @@ -1629,7 +1630,7 @@ class EmptyChangeset(EmptyCommit): "Use EmptyCommit instead of EmptyChangeset", DeprecationWarning) return super(EmptyCommit, cls).__new__(cls, *args, **kwargs) - def __init__(self, cs='0' * 40, repo=None, requested_revision=None, + def __init__(self, cs=EMPTY_COMMIT_ID, repo=None, requested_revision=None, alias=None, revision=-1, message='', author='', date=None): if requested_revision is not None: warnings.warn( diff --git a/rhodecode/templates/compare/compare_diff.mako b/rhodecode/templates/compare/compare_diff.mako --- a/rhodecode/templates/compare/compare_diff.mako +++ b/rhodecode/templates/compare/compare_diff.mako @@ -37,12 +37,12 @@
- r${c.source_commit.idx}:${h.short_id(c.source_commit.raw_id)}...r${c.target_commit.idx}:${h.short_id(c.target_commit.raw_id)}
+ r${c.commit_ranges[0].idx}:${h.short_id(c.commit_ranges[0].raw_id)}...r${c.commit_ranges[-1].idx}:${h.short_id(c.commit_ranges[-1].raw_id)}
% endif