diff --git a/rhodecode/api/views/pull_request_api.py b/rhodecode/api/views/pull_request_api.py --- a/rhodecode/api/views/pull_request_api.py +++ b/rhodecode/api/views/pull_request_api.py @@ -302,7 +302,7 @@ def merge_pull_request( request.environ, repo_name=target_repo.repo_name, username=apiuser.username, action='push', scm=target_repo.repo_type) - merge_response = PullRequestModel().merge( + merge_response = PullRequestModel().merge_repo( pull_request, apiuser, extras=extras) if merge_response.executed: PullRequestModel().close_pull_request( diff --git a/rhodecode/apps/repository/tests/test_repo_pullrequests.py b/rhodecode/apps/repository/tests/test_repo_pullrequests.py --- a/rhodecode/apps/repository/tests/test_repo_pullrequests.py +++ b/rhodecode/apps/repository/tests/test_repo_pullrequests.py @@ -618,7 +618,7 @@ class TestPullrequestsView(object): model_patcher = mock.patch.multiple( PullRequestModel, - merge=mock.Mock(return_value=MergeResponse( + merge_repo=mock.Mock(return_value=MergeResponse( True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)), merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE'))) diff --git a/rhodecode/apps/repository/views/repo_pull_requests.py b/rhodecode/apps/repository/views/repo_pull_requests.py --- a/rhodecode/apps/repository/views/repo_pull_requests.py +++ b/rhodecode/apps/repository/views/repo_pull_requests.py @@ -340,7 +340,8 @@ class RepoPullRequestsView(RepoAppView, # check merge capabilities _merge_check = MergeCheck.validate( pull_request_latest, user=self._rhodecode_user, - translator=self.request.translate, force_shadow_repo_refresh=force_refresh) + translator=self.request.translate, + force_shadow_repo_refresh=force_refresh) c.pr_merge_errors = _merge_check.error_details c.pr_merge_possible = not _merge_check.failed c.pr_merge_message = _merge_check.merge_msg @@ -1063,7 +1064,7 @@ class RepoPullRequestsView(RepoAppView, def _merge_pull_request(self, pull_request, user, extras): _ = self.request.translate - merge_resp = PullRequestModel().merge(pull_request, user, extras=extras) + merge_resp = PullRequestModel().merge_repo(pull_request, user, extras=extras) if merge_resp.executed: log.debug("The merge was successful, closing the pull request.") diff --git a/rhodecode/lib/middleware/simplevcs.py b/rhodecode/lib/middleware/simplevcs.py --- a/rhodecode/lib/middleware/simplevcs.py +++ b/rhodecode/lib/middleware/simplevcs.py @@ -204,13 +204,14 @@ class SimpleVCS(object): # Only proceed if we got a pull request and if acl repo name from # URL equals the target repo name of the pull request. - if pull_request and (acl_repo_name == - pull_request.target_repo.repo_name): + if pull_request and \ + (acl_repo_name == pull_request.target_repo.repo_name): + repo_id = pull_request.target_repo.repo_id # Get file system path to shadow repository. workspace_id = PullRequestModel()._workspace_id(pull_request) target_vcs = pull_request.target_repo.scm_instance() vcs_repo_name = target_vcs._get_shadow_repository_path( - workspace_id) + repo_id, workspace_id) # Store names for later usage. self.vcs_repo_name = vcs_repo_name 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 @@ -451,7 +451,7 @@ class BaseRepository(object): """ raise NotImplementedError - def merge(self, target_ref, source_repo, source_ref, workspace_id, + def merge(self, repo_id, workspace_id, target_ref, source_repo, source_ref, user_name='', user_email='', message='', dry_run=False, use_rebase=False, close_branch=False): """ @@ -465,13 +465,14 @@ class BaseRepository(object): 'possible', 'executed', 'source_commit', 'target_commit', 'merge_commit'. + :param repo_id: `repo_id` target repo id. + :param workspace_id: `workspace_id` unique identifier. :param target_ref: `target_ref` points to the commit on top of which the `source_ref` should be merged. :param source_repo: The repository that contains the commits to be merged. :param source_ref: `source_ref` points to the topmost commit from the `source_repo` which should be merged. - :param workspace_id: `workspace_id` unique identifier. :param user_name: Merge commit `user_name`. :param user_email: Merge commit `user_email`. :param message: Merge commit `message`. @@ -492,12 +493,9 @@ class BaseRepository(object): if not message: raise ValueError('message cannot be empty') - shadow_repository_path = self._maybe_prepare_merge_workspace( - workspace_id, target_ref, source_ref) - try: return self._merge_repo( - shadow_repository_path, target_ref, source_repo, + repo_id, workspace_id, target_ref, source_repo, source_ref, message, user_name, user_email, dry_run=dry_run, use_rebase=use_rebase, close_branch=close_branch) except RepositoryError: @@ -507,14 +505,15 @@ class BaseRepository(object): return MergeResponse( False, False, None, MergeFailureReason.UNKNOWN) - def _merge_repo(self, shadow_repository_path, target_ref, + def _merge_repo(self, repo_id, workspace_id, target_ref, source_repo, source_ref, merge_message, merger_name, merger_email, dry_run=False, use_rebase=False, close_branch=False): """Internal implementation of merge.""" raise NotImplementedError - def _maybe_prepare_merge_workspace(self, workspace_id, target_ref, source_ref): + def _maybe_prepare_merge_workspace( + self, repo_id, workspace_id, target_ref, source_ref): """ Create the merge workspace. @@ -522,10 +521,27 @@ class BaseRepository(object): """ raise NotImplementedError - def _get_shadow_repository_path(self, workspace_id): - raise NotImplementedError + def _get_legacy_shadow_repository_path(self, workspace_id): + """ + Legacy version that was used before. We still need it for + backward compat + """ + return os.path.join( + os.path.dirname(self.path), + '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) - def cleanup_merge_workspace(self, workspace_id): + def _get_shadow_repository_path(self, repo_id, workspace_id): + # The name of the shadow repository must start with '.', so it is + # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. + legacy_repository_path = self._get_legacy_shadow_repository_path(workspace_id) + if os.path.exists(legacy_repository_path): + return legacy_repository_path + else: + return os.path.join( + os.path.dirname(self.path), + '.__shadow_repo_%s_%s' % (repo_id, workspace_id)) + + def cleanup_merge_workspace(self, repo_id, workspace_id): """ Remove merge workspace. @@ -534,7 +550,7 @@ class BaseRepository(object): :param workspace_id: `workspace_id` unique identifier. """ - shadow_repository_path = self._get_shadow_repository_path(workspace_id) + shadow_repository_path = self._get_shadow_repository_path(repo_id, workspace_id) shadow_repository_path_del = '{}.{}.delete'.format( shadow_repository_path, time.time()) diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/rhodecode/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/rhodecode/lib/vcs/backends/git/repository.py @@ -902,7 +902,19 @@ class GitRepository(BaseRepository): return '%s%d' % (prefix, branch_id) - def _merge_repo(self, shadow_repository_path, target_ref, + def _maybe_prepare_merge_workspace( + self, repo_id, workspace_id, target_ref, source_ref): + shadow_repository_path = self._get_shadow_repository_path( + repo_id, workspace_id) + if not os.path.exists(shadow_repository_path): + self._local_clone( + shadow_repository_path, target_ref.name, source_ref.name) + log.debug( + 'Prepared shadow repository in %s', shadow_repository_path) + + return shadow_repository_path + + def _merge_repo(self, repo_id, workspace_id, target_ref, source_repo, source_ref, merge_message, merger_name, merger_email, dry_run=False, use_rebase=False, close_branch=False): @@ -912,7 +924,10 @@ class GitRepository(BaseRepository): return MergeResponse( False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) - shadow_repo = GitRepository(shadow_repository_path) + shadow_repository_path = self._maybe_prepare_merge_workspace( + repo_id, workspace_id, target_ref, source_ref) + shadow_repo = self._get_shadow_instance(shadow_repository_path) + # checkout source, if it's different. Otherwise we could not # fetch proper commits for merge testing if source_ref.name != target_ref.name: @@ -929,7 +944,7 @@ class GitRepository(BaseRepository): # Need to reload repo to invalidate the cache, or otherwise we cannot # retrieve the last target commit. - shadow_repo = GitRepository(shadow_repository_path) + shadow_repo = self._get_shadow_instance(shadow_repository_path) if target_ref.commit_id != shadow_repo.branches[target_ref.name]: log.warning('Shadow Target ref %s commit mismatch %s vs %s', target_ref, target_ref.commit_id, @@ -989,18 +1004,3 @@ class GitRepository(BaseRepository): return MergeResponse( merge_possible, merge_succeeded, merge_ref, merge_failure_reason) - - def _get_shadow_repository_path(self, workspace_id): - # The name of the shadow repository must start with '.', so it is - # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. - return os.path.join( - os.path.dirname(self.path), - '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) - - def _maybe_prepare_merge_workspace(self, workspace_id, target_ref, source_ref): - shadow_repository_path = self._get_shadow_repository_path(workspace_id) - if not os.path.exists(shadow_repository_path): - self._local_clone( - shadow_repository_path, target_ref.name, source_ref.name) - - return shadow_repository_path diff --git a/rhodecode/lib/vcs/backends/hg/repository.py b/rhodecode/lib/vcs/backends/hg/repository.py --- a/rhodecode/lib/vcs/backends/hg/repository.py +++ b/rhodecode/lib/vcs/backends/hg/repository.py @@ -681,15 +681,10 @@ class MercurialRepository(BaseRepository return ref.name return self._remote.ctx_branch(ref.commit_id) - def _get_shadow_repository_path(self, workspace_id): - # The name of the shadow repository must start with '.', so it is - # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. - return os.path.join( - os.path.dirname(self.path), - '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) - - def _maybe_prepare_merge_workspace(self, workspace_id, unused_target_ref, unused_source_ref): - shadow_repository_path = self._get_shadow_repository_path(workspace_id) + def _maybe_prepare_merge_workspace( + self, repo_id, workspace_id, unused_target_ref, unused_source_ref): + shadow_repository_path = self._get_shadow_repository_path( + repo_id, workspace_id) if not os.path.exists(shadow_repository_path): self._local_clone(shadow_repository_path) log.debug( @@ -697,7 +692,7 @@ class MercurialRepository(BaseRepository return shadow_repository_path - def _merge_repo(self, shadow_repository_path, target_ref, + def _merge_repo(self, repo_id, workspace_id, target_ref, source_repo, source_ref, merge_message, merger_name, merger_email, dry_run=False, use_rebase=False, close_branch=False): @@ -719,6 +714,8 @@ class MercurialRepository(BaseRepository return MergeResponse( False, False, None, MergeFailureReason.MISSING_TARGET_REF) + shadow_repository_path = self._maybe_prepare_merge_workspace( + repo_id, workspace_id, target_ref, source_ref) shadow_repo = self._get_shadow_instance(shadow_repository_path) log.debug('Pulling in target reference %s', target_ref) diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -1883,6 +1883,12 @@ class Repository(Base, BaseModel): return os.listdir(diff_cache_dir) return [] + def shadow_repos(self): + shadow_repos_pattern = '.__shadow_repo_{}'.format(self.repo_id) + return [ + x for x in os.listdir(os.path.dirname(self.repo_full_path)) + if x.startswith(shadow_repos_pattern)] + def get_new_name(self, repo_name): """ returns new full repository name based on assigned group and new new @@ -3762,7 +3768,7 @@ class PullRequest(Base, _PullRequestBase workspace_id = self.workspace_id vcs_obj = self.target_repo.scm_instance() shadow_repository_path = vcs_obj._get_shadow_repository_path( - workspace_id) + self.target_repo.repo_id, workspace_id) if os.path.isdir(shadow_repository_path): return vcs_obj._get_shadow_instance(shadow_repository_path) diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -583,7 +583,7 @@ class PullRequestModel(BaseModel): return commit_ids - def merge(self, pull_request, user, extras): + def merge_repo(self, pull_request, user, extras): log.debug("Merging pull request %s", pull_request.pull_request_id) merge_state = self._merge_pull_request(pull_request, user, extras) if merge_state.executed: @@ -616,6 +616,7 @@ class PullRequestModel(BaseModel): } workspace_id = self._workspace_id(pull_request) + repo_id = pull_request.target_repo.repo_id use_rebase = self._use_rebase_for_merging(pull_request) close_branch = self._close_branch_before_merging(pull_request) @@ -629,9 +630,10 @@ class PullRequestModel(BaseModel): target_vcs.config.set( 'rhodecode', 'RC_SCM_DATA', json.dumps(extras)) merge_state = target_vcs.merge( - target_ref, source_vcs, pull_request.source_ref_parts, - workspace_id, user_name=user.username, - user_email=user.email, message=message, use_rebase=use_rebase, + repo_id, workspace_id, target_ref, source_vcs, + pull_request.source_ref_parts, + user_name=user.username, user_email=user.email, + message=message, use_rebase=use_rebase, close_branch=close_branch) return merge_state @@ -1328,11 +1330,13 @@ class PullRequestModel(BaseModel): def _refresh_merge_state(self, pull_request, target_vcs, target_reference): workspace_id = self._workspace_id(pull_request) source_vcs = pull_request.source_repo.scm_instance() + repo_id = pull_request.target_repo.repo_id use_rebase = self._use_rebase_for_merging(pull_request) close_branch = self._close_branch_before_merging(pull_request) merge_state = target_vcs.merge( + repo_id, workspace_id, target_reference, source_vcs, pull_request.source_ref_parts, - workspace_id, dry_run=True, use_rebase=use_rebase, + dry_run=True, use_rebase=use_rebase, close_branch=close_branch) # Do not store the response if there was an unknown error. @@ -1398,11 +1402,12 @@ class PullRequestModel(BaseModel): def _cleanup_merge_workspace(self, pull_request): # Merging related cleanup + repo_id = pull_request.target_repo.repo_id target_scm = pull_request.target_repo.scm_instance() - workspace_id = 'pr-%s' % pull_request.pull_request_id + workspace_id = self._workspace_id(pull_request) try: - target_scm.cleanup_merge_workspace(workspace_id) + target_scm.cleanup_merge_workspace(repo_id, workspace_id) except NotImplementedError: pass diff --git a/rhodecode/tests/__init__.py b/rhodecode/tests/__init__.py --- a/rhodecode/tests/__init__.py +++ b/rhodecode/tests/__init__.py @@ -116,6 +116,13 @@ def get_new_dir(title): return get_normalized_path(path) +def repo_id_generator(name): + numeric_hash = 0 + for char in name: + numeric_hash += (ord(char)) + return numeric_hash + + @pytest.mark.usefixtures('app', 'index_location') class TestController(object): diff --git a/rhodecode/tests/lib/middleware/test_simplevcs.py b/rhodecode/tests/lib/middleware/test_simplevcs.py --- a/rhodecode/tests/lib/middleware/test_simplevcs.py +++ b/rhodecode/tests/lib/middleware/test_simplevcs.py @@ -333,7 +333,7 @@ class TestShadowRepoExposure(object): workspace_id = PullRequestModel()._workspace_id(pull_request) target_vcs = pull_request.target_repo.scm_instance() vcs_repo_name = target_vcs._get_shadow_repository_path( - workspace_id) + pull_request.target_repo.repo_id, workspace_id) assert controller.vcs_repo_name == vcs_repo_name assert controller.url_repo_name == shadow_url diff --git a/rhodecode/tests/models/test_pullrequest.py b/rhodecode/tests/models/test_pullrequest.py --- a/rhodecode/tests/models/test_pullrequest.py +++ b/rhodecode/tests/models/test_pullrequest.py @@ -81,6 +81,7 @@ class TestPullRequestModel(object): self.source_commit = self.pull_request.source_ref_parts.commit_id self.target_commit = self.pull_request.target_ref_parts.commit_id self.workspace_id = 'pr-%s' % self.pull_request.pull_request_id + self.repo_id = self.pull_request.target_repo.repo_id @request.addfinalizer def cleanup_pull_request(): @@ -135,17 +136,19 @@ class TestPullRequestModel(object): assert pr_count == 1 def test_delete_calls_cleanup_merge(self, pull_request): + repo_id = pull_request.target_repo.repo_id PullRequestModel().delete(pull_request, pull_request.author) self.workspace_remove_mock.assert_called_once_with( - self.workspace_id) + repo_id, self.workspace_id) def test_close_calls_cleanup_and_hook(self, pull_request): PullRequestModel().close_pull_request( pull_request, pull_request.author) + repo_id = pull_request.target_repo.repo_id self.workspace_remove_mock.assert_called_once_with( - self.workspace_id) + repo_id, self.workspace_id) self.hook_mock.assert_called_with( self.pull_request, self.pull_request.author, 'close') @@ -161,9 +164,10 @@ class TestPullRequestModel(object): assert status is True assert msg.eval() == 'This pull request can be automatically merged.' self.merge_mock.assert_called_with( + self.repo_id, self.workspace_id, pull_request.target_ref_parts, pull_request.source_repo.scm_instance(), - pull_request.source_ref_parts, self.workspace_id, dry_run=True, + pull_request.source_ref_parts, dry_run=True, use_rebase=False, close_branch=False) assert pull_request._last_merge_source_rev == self.source_commit @@ -190,9 +194,10 @@ class TestPullRequestModel(object): msg.eval() == 'This pull request cannot be merged because of merge conflicts.') self.merge_mock.assert_called_with( + self.repo_id, self.workspace_id, pull_request.target_ref_parts, pull_request.source_repo.scm_instance(), - pull_request.source_ref_parts, self.workspace_id, dry_run=True, + pull_request.source_ref_parts, dry_run=True, use_rebase=False, close_branch=False) assert pull_request._last_merge_source_rev == self.source_commit @@ -222,9 +227,10 @@ class TestPullRequestModel(object): 'This pull request cannot be merged because of an unhandled' ' exception.') self.merge_mock.assert_called_with( + self.repo_id, self.workspace_id, pull_request.target_ref_parts, pull_request.source_repo.scm_instance(), - pull_request.source_ref_parts, self.workspace_id, dry_run=True, + pull_request.source_ref_parts, dry_run=True, use_rebase=False, close_branch=False) assert pull_request._last_merge_source_rev is None @@ -281,7 +287,7 @@ class TestPullRequestModel(object): True, True, merge_ref, MergeFailureReason.NONE) merge_extras['repository'] = pull_request.target_repo.repo_name - PullRequestModel().merge( + PullRequestModel().merge_repo( pull_request, pull_request.author, extras=merge_extras) message = ( @@ -295,9 +301,10 @@ class TestPullRequestModel(object): ) ) self.merge_mock.assert_called_with( + self.repo_id, self.workspace_id, pull_request.target_ref_parts, pull_request.source_repo.scm_instance(), - pull_request.source_ref_parts, self.workspace_id, + pull_request.source_ref_parts, user_name=user.username, user_email=user.email, message=message, use_rebase=False, close_branch=False ) @@ -320,7 +327,7 @@ class TestPullRequestModel(object): False, False, merge_ref, MergeFailureReason.MERGE_FAILED) merge_extras['repository'] = pull_request.target_repo.repo_name - PullRequestModel().merge( + PullRequestModel().merge_repo( pull_request, pull_request.author, extras=merge_extras) message = ( @@ -334,9 +341,10 @@ class TestPullRequestModel(object): ) ) self.merge_mock.assert_called_with( + self.repo_id, self.workspace_id, pull_request.target_ref_parts, pull_request.source_repo.scm_instance(), - pull_request.source_ref_parts, self.workspace_id, + pull_request.source_ref_parts, user_name=user.username, user_email=user.email, message=message, use_rebase=False, close_branch=False ) @@ -392,7 +400,7 @@ class TestIntegrationMerge(object): Session().commit() with mock.patch.dict(rhodecode.CONFIG, extra_config, clear=False): - merge_state = PullRequestModel().merge( + merge_state = PullRequestModel().merge_repo( pull_request, user_admin, extras=merge_extras) assert merge_state.executed @@ -409,7 +417,7 @@ class TestIntegrationMerge(object): with mock.patch('rhodecode.EXTENSIONS.PRE_PUSH_HOOK') as pre_pull: pre_pull.side_effect = RepositoryError("Disallow push!") - merge_status = PullRequestModel().merge( + merge_status = PullRequestModel().merge_repo( pull_request, user_admin, extras=merge_extras) assert not merge_status.executed @@ -429,7 +437,7 @@ class TestIntegrationMerge(object): merge_extras['repository'] = pull_request.target_repo.repo_name # TODO: johbo: Needed for sqlite, try to find an automatic way for it Session().commit() - merge_status = PullRequestModel().merge( + merge_status = PullRequestModel().merge_repo( pull_request, user_regular, extras=merge_extras) assert not merge_status.executed diff --git a/rhodecode/tests/vcs/test_git.py b/rhodecode/tests/vcs/test_git.py --- a/rhodecode/tests/vcs/test_git.py +++ b/rhodecode/tests/vcs/test_git.py @@ -566,7 +566,7 @@ TODO: To be written... def test_maybe_prepare_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', Reference('branch', 'master', 'unused'), + 2, 'pr2', Reference('branch', 'master', 'unused'), Reference('branch', 'master', 'unused')) assert os.path.isdir(workspace) @@ -575,13 +575,13 @@ TODO: To be written... # Calling it a second time should also succeed workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', Reference('branch', 'master', 'unused'), + 2, 'pr2', Reference('branch', 'master', 'unused'), Reference('branch', 'master', 'unused')) assert os.path.isdir(workspace) def test_maybe_prepare_merge_workspace_different_refs(self): workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', Reference('branch', 'master', 'unused'), + 2, 'pr2', Reference('branch', 'master', 'unused'), Reference('branch', 'develop', 'unused')) assert os.path.isdir(workspace) @@ -590,22 +590,22 @@ TODO: To be written... # Calling it a second time should also succeed workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', Reference('branch', 'master', 'unused'), + 2, 'pr2', Reference('branch', 'master', 'unused'), Reference('branch', 'develop', 'unused')) assert os.path.isdir(workspace) def test_cleanup_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( - 'pr3', Reference('branch', 'master', 'unused'), + 2, 'pr3', Reference('branch', 'master', 'unused'), Reference('branch', 'master', 'unused')) - self.repo.cleanup_merge_workspace('pr3') + self.repo.cleanup_merge_workspace(2, 'pr3') assert not os.path.exists(workspace) def test_cleanup_merge_workspace_invalid_workspace_id(self): # No assert: because in case of an inexistent workspace this function # should still succeed. - self.repo.cleanup_merge_workspace('pr4') + self.repo.cleanup_merge_workspace(1, 'pr4') def test_set_refs(self): test_ref = 'refs/test-refs/abcde' diff --git a/rhodecode/tests/vcs/test_hg.py b/rhodecode/tests/vcs/test_hg.py --- a/rhodecode/tests/vcs/test_hg.py +++ b/rhodecode/tests/vcs/test_hg.py @@ -31,7 +31,7 @@ from rhodecode.lib.vcs.backends.hg impor from rhodecode.lib.vcs.exceptions import ( RepositoryError, VCSError, NodeDoesNotExistError, CommitDoesNotExistError) from rhodecode.lib.vcs.nodes import FileNode, NodeKind, NodeState -from rhodecode.tests import TEST_HG_REPO, TEST_HG_REPO_CLONE +from rhodecode.tests import TEST_HG_REPO, TEST_HG_REPO_CLONE, repo_id_generator pytestmark = pytest.mark.backends("hg") @@ -46,7 +46,6 @@ def repo_path_generator(): i += 1 yield '%s-%d' % (TEST_HG_REPO_CLONE, i) - REPO_PATH_GENERATOR = repo_path_generator() @@ -553,7 +552,7 @@ TODO: To be written... def test_maybe_prepare_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', 'unused', 'unused2') + 1, 'pr2', 'unused', 'unused2') assert os.path.isdir(workspace) workspace_repo = MercurialRepository(workspace) @@ -561,20 +560,22 @@ TODO: To be written... # Calling it a second time should also succeed workspace = self.repo._maybe_prepare_merge_workspace( - 'pr2', 'unused', 'unused2') + 1, 'pr2', 'unused', 'unused2') assert os.path.isdir(workspace) def test_cleanup_merge_workspace(self): workspace = self.repo._maybe_prepare_merge_workspace( - 'pr3', 'unused', 'unused2') - self.repo.cleanup_merge_workspace('pr3') + 1, 'pr3', 'unused', 'unused2') + + assert os.path.isdir(workspace) + self.repo.cleanup_merge_workspace(1, 'pr3') assert not os.path.exists(workspace) def test_cleanup_merge_workspace_invalid_workspace_id(self): # No assert: because in case of an inexistent workspace this function # should still succeed. - self.repo.cleanup_merge_workspace('pr4') + self.repo.cleanup_merge_workspace(1, 'pr4') def test_merge_target_is_bookmark(self, vcsbackend_hg): target_repo = vcsbackend_hg.create_repo(number_of_commits=1) @@ -594,10 +595,10 @@ TODO: To be written... 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' - + workspace_id = 'test-merge' + repo_id = repo_id_generator(target_repo.path) merge_response = target_repo.merge( - target_ref, source_repo, source_ref, workspace, + repo_id, workspace_id, target_ref, source_repo, source_ref, 'test user', 'test@rhodecode.com', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse( @@ -638,10 +639,10 @@ TODO: To be written... source_repo._update(default_branch) source_repo.bookmark(bookmark_name) source_ref = Reference('book', bookmark_name, source_commit.raw_id) - workspace = 'test-merge' - + workspace_id = 'test-merge' + repo_id = repo_id_generator(target_repo.path) merge_response = target_repo.merge( - target_ref, source_repo, source_ref, workspace, + repo_id, workspace_id, target_ref, source_repo, source_ref, 'test user', 'test@rhodecode.com', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse( @@ -677,14 +678,15 @@ TODO: To be written... target_ref = Reference('branch', default_branch, target_commit.raw_id) source_ref = Reference('branch', default_branch, source_commit.raw_id) - workspace = 'test-merge' + workspace_id = 'test-merge' assert len(target_repo._heads(branch='default')) == 2 expected_merge_response = MergeResponse( False, False, None, MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS) + repo_id = repo_id_generator(target_repo.path) merge_response = target_repo.merge( - target_ref, source_repo, source_ref, workspace, + repo_id, workspace_id, target_ref, source_repo, source_ref, 'test user', 'test@rhodecode.com', 'merge message 1', dry_run=False) assert merge_response == expected_merge_response @@ -711,10 +713,11 @@ TODO: To be written... target_ref = Reference('branch', default_branch, target_commit.raw_id) source_ref = Reference('book', bookmark_name, source_commit.raw_id) - workspace = 'test-merge' + repo_id = repo_id_generator(target_repo.path) + workspace_id = 'test-merge' merge_response = target_repo.merge( - target_ref, source_repo, source_ref, workspace, + repo_id, workspace_id, target_ref, source_repo, source_ref, 'test user', 'test@rhodecode.com', 'merge message 1', dry_run=False, use_rebase=True) diff --git a/rhodecode/tests/vcs/test_hg_vcsserver_cache_invalidation.py b/rhodecode/tests/vcs/test_hg_vcsserver_cache_invalidation.py --- a/rhodecode/tests/vcs/test_hg_vcsserver_cache_invalidation.py +++ b/rhodecode/tests/vcs/test_hg_vcsserver_cache_invalidation.py @@ -95,7 +95,7 @@ class TestMercurialRemoteRepoInvalidatio references. """ from rhodecode.model.pull_request import PullRequestModel - + repo_id = pull_request.target_repo target_vcs = pull_request.target_repo.scm_instance() target_ref = pull_request.target_ref_parts source_ref = pull_request.source_ref_parts @@ -104,7 +104,7 @@ class TestMercurialRemoteRepoInvalidatio pr = PullRequestModel() workspace_id = pr._workspace_id(pull_request) shadow_repository_path = target_vcs._maybe_prepare_merge_workspace( - workspace_id, target_ref, source_ref) + repo_id, workspace_id, target_ref, source_ref) shadow_repo = target_vcs._get_shadow_instance(shadow_repository_path) # This will populate the cache of the mercurial repository object diff --git a/rhodecode/tests/vcs/test_repository.py b/rhodecode/tests/vcs/test_repository.py --- a/rhodecode/tests/vcs/test_repository.py +++ b/rhodecode/tests/vcs/test_repository.py @@ -30,6 +30,7 @@ from rhodecode.lib.vcs.backends.base imp from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError from rhodecode.lib.vcs.nodes import FileNode from rhodecode.tests.vcs.conftest import BackendTestMixin +from rhodecode.tests import repo_id_generator @pytest.mark.usefixtures("vcs_repository_support") @@ -268,7 +269,7 @@ class TestRepositoryGetCommonAncestor: @pytest.mark.backends("git", "hg") -class TestRepositoryMerge: +class TestRepositoryMerge(object): 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) @@ -287,7 +288,8 @@ class TestRepositoryMerge: 'branch', default_branch, self.target_commit.raw_id) self.source_ref = Reference( 'branch', default_branch, self.source_commit.raw_id) - self.workspace = 'test-merge' + self.workspace_id = 'test-merge' + self.repo_id = repo_id_generator(self.target_repo.path) def prepare_for_conflict(self, vcsbackend): self.target_repo = vcsbackend.create_repo(number_of_commits=1) @@ -302,13 +304,15 @@ class TestRepositoryMerge: 'branch', default_branch, self.target_commit.raw_id) self.source_ref = Reference( 'branch', default_branch, self.source_commit.raw_id) - self.workspace = 'test-merge' + self.workspace_id = 'test-merge' + self.repo_id = repo_id_generator(self.target_repo.path) 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, + self.repo_id, self.workspace_id, self.target_ref, self.source_repo, + self.source_ref, 'test user', 'test@rhodecode.com', 'merge message 1', dry_run=False) expected_merge_response = MergeResponse( @@ -334,7 +338,7 @@ class TestRepositoryMerge: merge_response.merge_ref.commit_id) merge_response = target_repo.merge( - target_ref, self.source_repo, self.source_ref, self.workspace, + self.repo_id, self.workspace_id, target_ref, self.source_repo, self.source_ref, 'test user', 'test@rhodecode.com', 'merge message 2', dry_run=False) expected_merge_response = MergeResponse( @@ -353,13 +357,13 @@ class TestRepositoryMerge: self.prepare_for_success(vcsbackend) merge_response = self.target_repo.merge( - self.target_ref, self.source_repo, self.source_ref, self.workspace, - dry_run=True) + self.repo_id, self.workspace_id, self.target_ref, self.source_repo, + self.source_ref, dry_run=True) # We call it twice so to make sure we can handle updates merge_response_update = self.target_repo.merge( - self.target_ref, self.source_repo, self.source_ref, self.workspace, - dry_run=True) + self.repo_id, self.workspace_id, self.target_ref, self.source_repo, + self.source_ref, dry_run=True) # Multiple merges may differ in their commit id. Therefore we set the # commit id to `None` before comparing the merge responses. @@ -381,13 +385,15 @@ class TestRepositoryMerge: False, False, None, MergeFailureReason.MERGE_FAILED) merge_response = self.target_repo.merge( - self.target_ref, self.source_repo, self.source_ref, self.workspace, + self.repo_id, self.workspace_id, self.target_ref, + self.source_repo, self.source_ref, 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) assert merge_response == expected_merge_response # We call it twice so to make sure we can handle updates merge_response = self.target_repo.merge( - self.target_ref, self.source_repo, self.source_ref, self.workspace, + self.repo_id, self.workspace_id, self.target_ref, self.source_repo, + self.source_ref, 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) assert merge_response == expected_merge_response @@ -400,8 +406,8 @@ class TestRepositoryMerge: 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) + self.repo_id, self.workspace_id, target_ref, self.source_repo, + self.source_ref, dry_run=True) assert merge_response == expected_merge_response @@ -414,7 +420,8 @@ class TestRepositoryMerge: 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, + self.repo_id, self.workspace_id, self.target_ref, + self.source_repo, source_ref, dry_run=True) assert merge_response == expected_merge_response @@ -427,29 +434,38 @@ class TestRepositoryMerge: with mock.patch.object(self.target_repo, '_merge_repo', side_effect=RepositoryError()): merge_response = self.target_repo.merge( - self.target_ref, self.source_repo, self.source_ref, - self.workspace, dry_run=True) + self.repo_id, self.workspace_id, self.target_ref, + self.source_repo, self.source_ref, + dry_run=True) assert merge_response == expected_merge_response def test_merge_invalid_user_name(self, vcsbackend): repo = vcsbackend.create_repo(number_of_commits=1) ref = Reference('branch', 'master', 'not_used') + workspace_id = 'test-errors-in-merge' + repo_id = repo_id_generator(workspace_id) with pytest.raises(ValueError): - repo.merge(ref, self, ref, 'workspace_id') + repo.merge(repo_id, workspace_id, ref, self, ref) def test_merge_invalid_user_email(self, vcsbackend): repo = vcsbackend.create_repo(number_of_commits=1) ref = Reference('branch', 'master', 'not_used') + workspace_id = 'test-errors-in-merge' + repo_id = repo_id_generator(workspace_id) with pytest.raises(ValueError): - repo.merge(ref, self, ref, 'workspace_id', 'user name') + repo.merge( + repo_id, workspace_id, ref, self, ref, 'user name') def test_merge_invalid_message(self, vcsbackend): repo = vcsbackend.create_repo(number_of_commits=1) ref = Reference('branch', 'master', 'not_used') + workspace_id = 'test-errors-in-merge' + repo_id = repo_id_generator(workspace_id) with pytest.raises(ValueError): repo.merge( - ref, self, ref, 'workspace_id', 'user name', 'user@email.com') + repo_id, workspace_id, ref, self, ref, + 'user name', 'user@email.com') @pytest.mark.usefixtures("vcs_repository_support") @@ -505,7 +521,7 @@ class TestRepositoryStrip(BackendTestMix @pytest.mark.backends('hg', 'git') -class TestRepositoryPull: +class TestRepositoryPull(object): def test_pull(self, vcsbackend): source_repo = vcsbackend.repo