diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 09ce22c606..7b1e37b63b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -67,10 +67,6 @@ jobs: run: | pip install --upgrade pip setuptools wheel pip install -e ".[dev]" - - name: setup git - run: | - git config --global user.email "dvctester@example.com" - git config --global user.name "DVC Tester" - name: run tests timeout-minutes: 40 run: >- diff --git a/dvc/testing/tmp_dir.py b/dvc/testing/tmp_dir.py index 4cfcbd926b..e79bec1601 100644 --- a/dvc/testing/tmp_dir.py +++ b/dvc/testing/tmp_dir.py @@ -51,8 +51,6 @@ from contextlib import contextmanager from functools import partialmethod -from funcy import lmap, retry - from dvc.utils import serialize from dvc.utils.fs import makedirs @@ -62,7 +60,7 @@ class TmpDir(pathlib.Path): @property def fs_path(self): - return str(self) + return os.fspath(self) @property def url(self): @@ -98,18 +96,18 @@ def init(self, *, scm=False, dvc=False, subdir=False): assert not scm or not hasattr(self, "scm") assert not dvc or not hasattr(self, "dvc") - str_path = os.fspath(self) - if scm: - git_init(str_path) + Git.init(self.fs_path).close() if dvc: self.dvc = Repo.init( - str_path, + self.fs_path, no_scm=not scm and not hasattr(self, "scm"), subdir=subdir, ) if scm: - self.scm = self.dvc.scm if hasattr(self, "dvc") else Git(str_path) + self.scm = ( + self.dvc.scm if hasattr(self, "dvc") else Git(self.fs_path) + ) if dvc and hasattr(self, "scm"): self.scm.commit("init dvc") @@ -264,7 +262,7 @@ def modify(self, *args, **kwargs): def _coerce_filenames(filenames): if isinstance(filenames, (str, bytes, pathlib.PurePath)): filenames = [filenames] - return lmap(os.fspath, filenames) + return list(map(os.fspath, filenames)) class WindowsTmpDir(TmpDir, pathlib.PureWindowsPath): @@ -273,16 +271,3 @@ class WindowsTmpDir(TmpDir, pathlib.PureWindowsPath): class PosixTmpDir(TmpDir, pathlib.PurePosixPath): pass - - -def git_init(path): - from git import Repo - from git.exc import GitCommandNotFound - - # NOTE: handles EAGAIN error on BSD systems (osx in our case). - # Otherwise when running tests you might get this exception: - # - # GitCommandNotFound: Cmd('git') not found due to: - # OSError('[Errno 35] Resource temporarily unavailable') - git = retry(5, GitCommandNotFound)(Repo.init)(path) - git.close() diff --git a/tests/basic_env.py b/tests/basic_env.py index f5e246a021..536a8261c3 100644 --- a/tests/basic_env.py +++ b/tests/basic_env.py @@ -6,8 +6,6 @@ import pytest import shortuuid -from git import Repo -from git.exc import GitCommandNotFound from dvc.repo import Repo as DvcRepo from dvc.utils.fs import remove @@ -116,24 +114,11 @@ class TestGitFixture(TestDirFixture): N_RETRIES = 5 def setUp(self): + from scmrepo.git import Git + super().setUp() - # NOTE: handles EAGAIN error on BSD systems (osx in our case). - # Otherwise when running tests you might get this exception: - # - # GitCommandNotFound: Cmd('git') not found due to: - # OSError('[Errno 35] Resource temporarily unavailable') - retries = self.N_RETRIES - while True: - try: - self.git = Repo.init() - break - except GitCommandNotFound: - retries -= 1 - if not retries: - raise - - self.git.index.add([self.CODE]) - self.git.index.commit("add code") + self.git = Git.init(".") + self.git.add_commit(self.CODE, message="add code") def tearDown(self): self.git.close() diff --git a/tests/conftest.py b/tests/conftest.py index f3ce802cb8..9a168ade0f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import os +import sys from contextlib import suppress import pytest @@ -161,7 +162,7 @@ def pytest_configure(config): enabled_remotes.add(remote_name) -@pytest.fixture() +@pytest.fixture def custom_template(tmp_dir, dvc): try: import importlib_resources @@ -185,3 +186,40 @@ def custom_template(tmp_dir, dvc): @pytest.fixture(autouse=True) def mocked_webbrowser_open(mocker): mocker.patch("webbrowser.open") + + +@pytest.fixture(autouse=True) +def isolate(tmp_path_factory, monkeypatch) -> None: + path = tmp_path_factory.mktemp("mock") + home_dir = path / "home" + home_dir.mkdir() + + if sys.platform == "win32": + home_drive, home_path = os.path.splitdrive(home_dir) + monkeypatch.setenv("USERPROFILE", str(home_dir)) + monkeypatch.setenv("HOMEDRIVE", home_drive) + monkeypatch.setenv("HOMEPATH", home_path) + + for env_var, sub_path in ( + ("APPDATA", "Roaming"), + ("LOCALAPPDATA", "Local"), + ): + path = home_dir / "AppData" / sub_path + path.mkdir(parents=True) + monkeypatch.setenv(env_var, os.fspath(path)) + else: + monkeypatch.setenv("HOME", str(home_dir)) + + monkeypatch.setenv("GIT_CONFIG_NOSYSTEM", "1") + contents = b""" +[user] +name=DVC Tester +email=dvctester@example.com +[init] +defaultBranch=master +""" + (home_dir / ".gitconfig").write_bytes(contents) + + import pygit2 + + pygit2.settings.search_path[pygit2.GIT_CONFIG_LEVEL_GLOBAL] = str(home_dir) diff --git a/tests/dir_helpers.py b/tests/dir_helpers.py index b1da1b3d41..e0943c7db8 100644 --- a/tests/dir_helpers.py +++ b/tests/dir_helpers.py @@ -52,19 +52,16 @@ import pytest from dvc.logger import disable_other_loggers -from dvc.testing.tmp_dir import git_init __all__ = [ "run_copy", "run_head", "erepo_dir", "git_dir", - "git_init", "git_upstream", "git_downstream", ] - # see https://github.com/iterative/dvc/issues/3167 disable_other_loggers() diff --git a/tests/func/metrics/test_diff.py b/tests/func/metrics/test_diff.py index 40efcf88eb..6df35ba0ba 100644 --- a/tests/func/metrics/test_diff.py +++ b/tests/func/metrics/test_diff.py @@ -148,10 +148,9 @@ def test_no_commits(tmp_dir): from scmrepo.git import Git from dvc.repo import Repo - from tests.dir_helpers import git_init - git_init(".") - assert Git().no_commits + git = Git.init(tmp_dir.fs_path) + assert git.no_commits assert Repo.init().metrics.diff() == {} diff --git a/tests/func/params/test_diff.py b/tests/func/params/test_diff.py index f8afbaf5de..836e46893e 100644 --- a/tests/func/params/test_diff.py +++ b/tests/func/params/test_diff.py @@ -129,10 +129,9 @@ def test_no_commits(tmp_dir): from scmrepo.git import Git from dvc.repo import Repo - from tests.dir_helpers import git_init - git_init(".") - assert Git().no_commits + git = Git.init(tmp_dir.fs_path) + assert git.no_commits assert Repo.init().params.diff() == {} diff --git a/tests/func/test_diff.py b/tests/func/test_diff.py index 0fad451629..976facc46c 100644 --- a/tests/func/test_diff.py +++ b/tests/func/test_diff.py @@ -293,10 +293,9 @@ def test_no_commits(tmp_dir): from scmrepo.git import Git from dvc.repo import Repo - from tests.dir_helpers import git_init - git_init(".") - assert Git().no_commits + git = Git.init(tmp_dir.fs_path) + assert git.no_commits assert Repo.init().diff() == {} diff --git a/tests/func/test_import.py b/tests/func/test_import.py index d4d19c6219..0bc6f8b5bd 100644 --- a/tests/func/test_import.py +++ b/tests/func/test_import.py @@ -4,6 +4,7 @@ import pytest from funcy import first +from scmrepo.git import Git from dvc.config import NoRemoteError from dvc.dvcfile import Dvcfile @@ -268,9 +269,7 @@ def test_pull_wildcard_imported_directory_stage(tmp_dir, dvc, erepo_dir): def test_push_wildcard_from_bare_git_repo( tmp_dir, make_tmp_dir, erepo_dir, local_cloud ): - import git - - git.Repo.init(os.fspath(tmp_dir), bare=True) + Git.init(tmp_dir.fs_path, bare=True).close() erepo_dir.add_remote(config=local_cloud.config) with erepo_dir.chdir(): @@ -381,9 +380,7 @@ def test_pull_no_rev_lock(erepo_dir, tmp_dir, dvc): def test_import_from_bare_git_repo( tmp_dir, make_tmp_dir, erepo_dir, local_cloud ): - import git - - git.Repo.init(os.fspath(tmp_dir), bare=True) + Git.init(tmp_dir.fs_path, bare=True).close() erepo_dir.add_remote(config=local_cloud.config) with erepo_dir.chdir(): diff --git a/tests/unit/fs/test_ssh.py b/tests/unit/fs/test_ssh.py index 60712e9b19..ff071091e8 100644 --- a/tests/unit/fs/test_ssh.py +++ b/tests/unit/fs/test_ssh.py @@ -122,7 +122,7 @@ def test_ssh_port(mock_file, config, expected_port): ), ( {"host": "example.com"}, - [os.path.expanduser("~/.ssh/not_default.key")], + ["~/.ssh/not_default.key"], ), ( { @@ -141,7 +141,12 @@ def test_ssh_port(mock_file, config, expected_port): ) def test_ssh_keyfile(mock_file, config, expected_keyfile): fs = SSHFileSystem(**config) - assert fs.fs_args.get("client_keys") == expected_keyfile + expected_keyfiles = ( + [os.path.expanduser(path) for path in expected_keyfile] + if expected_keyfile + else expected_keyfile + ) + assert fs.fs_args.get("client_keys") == expected_keyfiles mock_ssh_multi_key_config = """