def test_local_merge_of_two_branches_of_the_same_repo(self, backend_hg): commits = [ { 'message': 'a' }, { 'message': 'b', 'branch': 'b' }, ] repo = backend_hg.create_repo(commits) commit_ids = backend_hg.commit_ids target_ref = Reference(type='branch', name='default', commit_id=commit_ids['a']) source_ref = Reference(type='branch', name='b', commit_id=commit_ids['b']) merge_message = 'Merge message\n\nDescription:...' user_name = 'Albert Einstein' user_email = '*****@*****.**' vcs_repo = repo.scm_instance() merge_commit_id, needs_push = vcs_repo._local_merge( target_ref, merge_message, user_name, user_email, source_ref) assert merge_commit_id != source_ref.commit_id assert needs_push is True commit = vcs_repo.get_commit(merge_commit_id) assert commit.merge is True assert commit.message == merge_message
def test_local_merge_source_is_fast_forward(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) source_repo = vcsbackend_hg.clone_repo(target_repo) target_rev = target_repo.branches['default'] target_ref = Reference(type='branch', name='default', commit_id=target_rev) vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2') source_repo = MercurialRepository(source_repo.path) source_rev = source_repo.branches['default'] source_ref = Reference(type='branch', name='default', commit_id=source_rev) target_repo._local_pull(source_repo.path, source_ref) merge_message = 'Merge message\n\nDescription:...' user_name = 'Albert Einstein' user_email = '*****@*****.**' merge_commit_id, needs_push = target_repo._local_merge( target_ref, merge_message, user_name, user_email, source_ref) assert merge_commit_id == source_rev assert needs_push target_repo = MercurialRepository(target_repo.path) assert target_repo.commit_ids[-2] == target_rev assert target_repo.commit_ids[-1] == source_rev assert not os.path.exists( os.path.join(target_repo.path, '.hg', 'merge', 'state'))
def test_maybe_prepare_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( 'pr2', Reference('branch', 'master', 'unused')) assert os.path.isdir(workspace) workspace_repo = GitRepository(workspace) assert workspace_repo.branches == self.repo.branches # Calling it a second time should also succeed workspace = self.repo._maybe_prepare_merge_workspace( 'pr2', Reference('branch', 'master', 'unused')) assert os.path.isdir(workspace)
def test_merge_rebase_source_is_updated_bookmark(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) source_repo = vcsbackend_hg.clone_repo(target_repo) vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1') vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2') imc = source_repo.in_memory_commit imc.add(FileNode('file_x', content=source_repo.name)) imc.commit(message=u'Automatic commit from repo merge test', author=u'Automatic') target_commit = target_repo.get_commit() source_commit = source_repo.get_commit() vcsbackend_hg.add_file(source_repo, 'LICENSE', 'LICENSE Info') default_branch = target_repo.DEFAULT_BRANCH_NAME bookmark_name = 'bookmark' source_repo._update(default_branch) source_repo.bookmark(bookmark_name) target_ref = Reference('branch', default_branch, target_commit.raw_id) source_ref = Reference('book', bookmark_name, source_commit.raw_id) workspace = 'test-merge' with mock.patch.object(rhodecode.lib.vcs.conf.settings, 'HG_USE_REBASE_FOR_MERGING', return_value=True): merge_response = target_repo.merge(target_ref, source_repo, source_ref, workspace, 'test user', '*****@*****.**', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse(True, True, merge_response.merge_commit_id, MergeFailureReason.NONE) assert merge_response == expected_merge_response target_repo = backends.get_backend(vcsbackend_hg.alias)( target_repo.path) last_commit = target_repo.get_commit() assert last_commit.message == source_commit.message assert last_commit.author == source_commit.author # This checks that we effectively did a rebase assert last_commit.raw_id != source_commit.raw_id # Check the target has only 4 commits: 2 were already in target and # only two should have been added assert len(target_repo.commit_ids) == 2 + 2
def prepare_for_conflict(self, vcsbackend): self.target_repo = vcsbackend.create_repo(number_of_commits=1) self.source_repo = vcsbackend.clone_repo(self.target_repo) vcsbackend.add_file(self.target_repo, 'README_MERGE', 'Version 1') vcsbackend.add_file(self.source_repo, 'README_MERGE', 'Version 2') self.target_commit = self.target_repo.get_commit() self.source_commit = self.source_repo.get_commit() # This only works for Git and Mercurial default_branch = self.target_repo.DEFAULT_BRANCH_NAME self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id) self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id) self.workspace = 'test-merge'
def test_local_pull_branch(self): target_repo = self.get_empty_repo() source_repo = self.get_clone_repo() default = Reference('branch', 'default', source_repo.branches['default']) target_repo._local_pull(source_repo.path, default) target_repo = MercurialRepository(target_repo.path) assert ( target_repo.branches['default'] == source_repo.branches['default']) stable = Reference('branch', 'stable', source_repo.branches['stable']) target_repo._local_pull(source_repo.path, stable) target_repo = MercurialRepository(target_repo.path) assert target_repo.branches['stable'] == source_repo.branches['stable']
def test_validate_pull_reference_raises_on_missing_reference( self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) reference = Reference('book', 'invalid_reference', 'a' * 40) with pytest.raises(CommitDoesNotExistError): target_repo._validate_pull_reference(reference)
def test_local_pull_commit(self): target_repo = self.get_empty_repo() source_repo = self.get_clone_repo() commits = list(source_repo.get_commits(branch_name='default')) commit_id = commits[-5].raw_id commit = Reference('rev', commit_id, commit_id) target_repo._local_pull(source_repo.path, commit) target_repo = MercurialRepository(target_repo.path) assert target_repo.branches['default'] == commit_id commit_id = commits[-3].raw_id commit = Reference('rev', commit_id, commit_id) target_repo._local_pull(source_repo.path, commit) target_repo = MercurialRepository(target_repo.path) assert target_repo.branches['default'] == commit_id
def test_merge_target_is_bookmark(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) source_repo = vcsbackend_hg.clone_repo(target_repo) vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1') vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2') imc = source_repo.in_memory_commit imc.add(FileNode('file_x', content=source_repo.name)) imc.commit(message=u'Automatic commit from repo merge test', author=u'Automatic') target_commit = target_repo.get_commit() source_commit = source_repo.get_commit() default_branch = target_repo.DEFAULT_BRANCH_NAME bookmark_name = 'bookmark' target_repo._update(default_branch) target_repo.bookmark(bookmark_name) target_ref = Reference('book', bookmark_name, target_commit.raw_id) source_ref = Reference('branch', default_branch, source_commit.raw_id) workspace = 'test-merge' merge_response = target_repo.merge(target_ref, source_repo, source_ref, workspace, 'test user', '*****@*****.**', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse(True, True, merge_response.merge_commit_id, MergeFailureReason.NONE) assert merge_response == expected_merge_response target_repo = backends.get_backend(vcsbackend_hg.alias)( target_repo.path) target_commits = list(target_repo.get_commits()) commit_ids = [c.raw_id for c in target_commits[:-1]] assert source_ref.commit_id in commit_ids assert target_ref.commit_id in commit_ids merge_commit = target_commits[-1] assert merge_commit.raw_id == merge_response.merge_commit_id assert merge_commit.message.strip() == 'merge message 1' assert merge_commit.author == 'test user <*****@*****.**>' # Check the bookmark was updated in the target repo assert (target_repo.bookmarks[bookmark_name] == merge_response.merge_commit_id)
def prepare_for_success(self, vcsbackend): self.target_repo = vcsbackend.create_repo(number_of_commits=1) self.source_repo = vcsbackend.clone_repo(self.target_repo) vcsbackend.add_file(self.target_repo, 'README_MERGE1', 'Version 1') vcsbackend.add_file(self.source_repo, 'README_MERGE2', 'Version 2') imc = self.source_repo.in_memory_commit imc.add(FileNode('file_x', content=self.source_repo.name)) imc.commit(message=u'Automatic commit from repo merge test', author=u'Automatic') self.target_commit = self.target_repo.get_commit() self.source_commit = self.source_repo.get_commit() # This only works for Git and Mercurial default_branch = self.target_repo.DEFAULT_BRANCH_NAME self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id) self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id) self.workspace = 'test-merge'
def _refresh_reference(self, reference, vcs_repository): if reference.type in ('branch', 'book'): name_or_id = reference.name else: name_or_id = reference.commit_id refreshed_commit = vcs_repository.get_commit(name_or_id) refreshed_reference = Reference(reference.type, reference.name, refreshed_commit.raw_id) return refreshed_reference
def test_local_pull_bookmark(self): target_repo = self.get_empty_repo() source_repo = self.get_clone_repo() commits = list(source_repo.get_commits(branch_name='default')) foo1_id = commits[-5].raw_id foo1 = Reference('book', 'foo1', foo1_id) source_repo._update(foo1_id) source_repo.bookmark('foo1') foo2_id = commits[-3].raw_id foo2 = Reference('book', 'foo2', foo2_id) source_repo._update(foo2_id) source_repo.bookmark('foo2') target_repo._local_pull(source_repo.path, foo1) target_repo = MercurialRepository(target_repo.path) assert target_repo.branches['default'] == commits[-5].raw_id target_repo._local_pull(source_repo.path, foo2) target_repo = MercurialRepository(target_repo.path) assert target_repo.branches['default'] == commits[-3].raw_id
def test_merge_success(self, vcsbackend): self.prepare_for_success(vcsbackend) merge_response = self.target_repo.merge(self.target_ref, self.source_repo, self.source_ref, self.workspace, 'test user', '*****@*****.**', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse(True, True, merge_response.merge_commit_id, MergeFailureReason.NONE) assert merge_response == expected_merge_response target_repo = backends.get_backend(vcsbackend.alias)( self.target_repo.path) target_commits = list(target_repo.get_commits()) commit_ids = [c.raw_id for c in target_commits[:-1]] assert self.source_ref.commit_id in commit_ids assert self.target_ref.commit_id in commit_ids merge_commit = target_commits[-1] assert merge_commit.raw_id == merge_response.merge_commit_id assert merge_commit.message.strip() == 'merge message 1' assert merge_commit.author == 'test user <*****@*****.**>' # We call it twice so to make sure we can handle updates target_ref = Reference(self.target_ref.type, self.target_ref.name, merge_response.merge_commit_id) merge_response = target_repo.merge(target_ref, self.source_repo, self.source_ref, self.workspace, 'test user', '*****@*****.**', 'merge message 2', dry_run=False) expected_merge_response = MergeResponse(True, True, merge_response.merge_commit_id, MergeFailureReason.NONE) assert merge_response == expected_merge_response target_repo = backends.get_backend(vcsbackend.alias)( self.target_repo.path) merge_commit = target_repo.get_commit(merge_response.merge_commit_id) assert merge_commit.message.strip() == 'merge message 1' assert merge_commit.author == 'test user <*****@*****.**>'
def test_merge_target_has_multiple_heads(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=2) source_repo = vcsbackend_hg.clone_repo(target_repo) vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1') vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2') # add an extra head to the target repo imc = target_repo.in_memory_commit imc.add(FileNode('file_x', content='foo')) commits = list(target_repo.get_commits()) imc.commit(message=u'Automatic commit from repo merge test', author=u'Automatic', parents=commits[0:1]) target_commit = target_repo.get_commit() source_commit = source_repo.get_commit() default_branch = target_repo.DEFAULT_BRANCH_NAME target_repo._update(default_branch) target_ref = Reference('branch', default_branch, target_commit.raw_id) source_ref = Reference('branch', default_branch, source_commit.raw_id) workspace = 'test-merge' assert len(target_repo._heads(branch='default')) == 2 expected_merge_response = MergeResponse( False, False, None, MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS) merge_response = target_repo.merge(target_ref, source_repo, source_ref, workspace, 'test user', '*****@*****.**', 'merge message 1', dry_run=False) assert merge_response == expected_merge_response
def test_local_merge_raises_exception_on_conflict(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) source_repo = vcsbackend_hg.clone_repo(target_repo) vcsbackend_hg.add_file(target_repo, 'README_MERGE', 'Version 1') target_repo = MercurialRepository(target_repo.path) target_rev = target_repo.branches['default'] target_ref = Reference(type='branch', name='default', commit_id=target_rev) vcsbackend_hg.add_file(source_repo, 'README_MERGE', 'Version 2') source_repo = MercurialRepository(source_repo.path) source_rev = source_repo.branches['default'] source_ref = Reference(type='branch', name='default', commit_id=source_rev) target_repo._local_pull(source_repo.path, source_ref) with pytest.raises(RepositoryError): target_repo._local_merge(target_ref, 'merge_message', 'user name', '*****@*****.**', source_ref) # Check we are not left in an intermediate merge state assert not os.path.exists( os.path.join(target_repo.path, '.hg', 'merge', 'state'))
def test_merge_source_is_bookmark(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) source_repo = vcsbackend_hg.clone_repo(target_repo) imc = source_repo.in_memory_commit imc.add(FileNode('file_x', content=source_repo.name)) imc.commit(message=u'Automatic commit from repo merge test', author=u'Automatic') target_commit = target_repo.get_commit() source_commit = source_repo.get_commit() default_branch = target_repo.DEFAULT_BRANCH_NAME bookmark_name = 'bookmark' target_ref = Reference('branch', default_branch, target_commit.raw_id) source_repo._update(default_branch) source_repo.bookmark(bookmark_name) source_ref = Reference('book', bookmark_name, source_commit.raw_id) workspace = 'test-merge' merge_response = target_repo.merge(target_ref, source_repo, source_ref, workspace, 'test user', '*****@*****.**', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse(True, True, merge_response.merge_commit_id, MergeFailureReason.NONE) assert merge_response == expected_merge_response target_repo = backends.get_backend(vcsbackend_hg.alias)( target_repo.path) target_commits = list(target_repo.get_commits()) commit_ids = [c.raw_id for c in target_commits] assert source_ref.commit_id == commit_ids[-1] assert target_ref.commit_id == commit_ids[-2]
def test_merge_missing_commit(self, vcsbackend): self.prepare_for_success(vcsbackend) expected_merge_response = MergeResponse( False, False, None, MergeFailureReason.MISSING_COMMIT) source_ref = Reference(self.source_ref.type, 'not_existing', self.source_ref.commit_id) merge_response = self.target_repo.merge(self.target_ref, self.source_repo, source_ref, self.workspace, dry_run=True) assert merge_response == expected_merge_response
def test_merge_target_is_not_head(self, vcsbackend): self.prepare_for_success(vcsbackend) expected_merge_response = MergeResponse( False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) target_ref = Reference(self.target_ref.type, self.target_ref.name, '0' * 40) merge_response = self.target_repo.merge(target_ref, self.source_repo, self.source_ref, self.workspace, dry_run=True) assert merge_response == expected_merge_response
def test_local_merge_source_is_integrated(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) target_rev = target_repo.branches['default'] target_ref = Reference(type='branch', name='default', commit_id=target_rev) merge_message = 'Merge message\n\nDescription:...' user_name = 'Albert Einstein' user_email = '*****@*****.**' merge_commit_id, needs_push = target_repo._local_merge( target_ref, merge_message, user_name, user_email, target_ref) assert merge_commit_id == target_rev assert not needs_push target_repo = MercurialRepository(target_repo.path) assert target_repo.commit_ids[-1] == target_rev assert not os.path.exists( os.path.join(target_repo.path, '.hg', 'merge', 'state'))
def test_cleanup_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( 'pr3', Reference('branch', 'master', 'unused')) self.repo.cleanup_merge_workspace('pr3') assert not os.path.exists(workspace)
def test_local_pull_from_same_repo(self): reference = Reference('branch', 'default', None) with pytest.raises(ValueError): self.repo._local_pull(self.repo.path, reference)
def test_merge_invalid_message(self, vcsbackend): repo = vcsbackend.create_repo(number_of_commits=1) ref = Reference('branch', 'master', 'not_used') with pytest.raises(ValueError): repo.merge(ref, self, ref, 'workspace_id', 'user name', '*****@*****.**')