From 355369c31de619aa20df028a1d05e9265386f164 Mon Sep 17 00:00:00 2001 From: Amrit Ghimire Date: Sun, 24 Oct 2021 19:52:10 +0545 Subject: [PATCH 1/2] test: fix test failure in case of different default branch When the git config has set global `init.defaultBranch` different than master, a few test cases were failing. Currently, the test case is assuming the default branch to be set as master. This commit will introduce **initial_branch** option to git init call which will ensure *master* branch is used as default for out test cases. Set default git branch to main for test CI Since main is going to be new default branch, it will let the test case handle the scenario where default branch is set other than master. Introduce isolation for git configuration --- .github/workflows/tests.yaml | 4 ---- dvc/testing/tmp_dir.py | 29 +++++++---------------------- tests/basic_env.py | 23 ++++------------------- tests/conftest.py | 32 +++++++++++++++++++++++++++++++- tests/dir_helpers.py | 3 --- tests/func/metrics/test_diff.py | 5 ++--- tests/func/params/test_diff.py | 5 ++--- tests/func/test_diff.py | 5 ++--- tests/func/test_import.py | 9 +++------ tests/unit/fs/test_ssh.py | 9 +++++++-- 10 files changed, 58 insertions(+), 66 deletions(-) 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..ebc6856f65 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,32 @@ 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) + 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 = """ From d3c3e6f4bfc9eef1ce41538fd0d42a32ddece167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Thu, 6 Jan 2022 15:58:09 +0545 Subject: [PATCH 2/2] try fixing windows --- tests/conftest.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index ebc6856f65..9a168ade0f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -199,6 +199,14 @@ def isolate(tmp_path_factory, monkeypatch) -> None: 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))