From 8a318f4299cd4f8b306f124900c7bd66eed3419a Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 24 Jul 2020 14:03:23 +0200 Subject: [PATCH] Windows fixes - Ignore errors when executing `shutil.rmtree()`, because it seems like it's common to fail when deleting git repos on Windows, and since these are temp files, we don't really care that much there's garbage left. Any good OS should clean the temp folders automatically. - Always find Jinja templates in `PosixPath` mode. - Ignore `OSError` when trying to enter a possibly git root directory. This is yielded by Windows when the path is a URL and we don't really care about it. - Fix some tests with non-windows haradcoded stuff. - Fix a test that was using a Bash script. Modified to be Python, which should work fine cross-system. - Do not modify EOL in CI. --- .github/workflows/ci.yml | 2 ++ copier/main.py | 2 +- copier/tools.py | 6 ++---- copier/vcs.py | 6 ++---- tests/demo_migrations/copier.yaml | 6 +++--- tests/demo_migrations/tasks.py | 13 +++++++++++++ tests/demo_migrations/tasks.sh | 4 ---- tests/test_config.py | 6 +++--- tests/test_migrations.py | 4 ++-- tests/test_vcs.py | 2 +- 10 files changed, 29 insertions(+), 22 deletions(-) create mode 100755 tests/demo_migrations/tasks.py delete mode 100755 tests/demo_migrations/tasks.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b792e8fb..920ca198a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,8 @@ jobs: shell: bash - run: git config --global user.email copier@copier shell: bash + - run: git config --global core.autocrlf input + shell: bash - run: python -m pip install poetry poetry-dynamic-versioning shell: bash - run: poetry install diff --git a/copier/main.py b/copier/main.py index 2b753235a..ee8290d59 100644 --- a/copier/main.py +++ b/copier/main.py @@ -147,7 +147,7 @@ def copy( raise finally: if is_update: - shutil.rmtree(conf.src_path) + shutil.rmtree(conf.src_path, ignore_errors=True) def copy_local(conf: ConfigData) -> None: diff --git a/copier/tools.py b/copier/tools.py index e0a55c320..c84490600 100644 --- a/copier/tools.py +++ b/copier/tools.py @@ -152,10 +152,8 @@ def __init__(self, conf: ConfigData) -> None: ) def __call__(self, fullpath: StrOrPath) -> str: - relpath = ( - str(fullpath).replace(str(self.conf.src_path), "", 1).lstrip(os.path.sep) - ) - tmpl = self.env.get_template(relpath) + relpath = Path(fullpath).relative_to(self.conf.src_path).as_posix() + tmpl = self.env.get_template(str(relpath)) return tmpl.render(**self.data) def string(self, string: StrOrPath) -> str: diff --git a/copier/vcs.py b/copier/vcs.py index a5a8bef60..26a89c7af 100644 --- a/copier/vcs.py +++ b/copier/vcs.py @@ -1,5 +1,4 @@ import re -import shutil import tempfile from pathlib import Path @@ -25,8 +24,8 @@ def is_git_repo_root(path: Path) -> bool: """Indicate if a given path is a git repo root directory.""" try: with local.cwd(path / ".git"): - return bool(git("rev-parse", "--is-inside-git-dir") == "true\n") - except (FileNotFoundError, NotADirectoryError): + return bool(git("rev-parse", "--is-inside-git-dir").strip() == "true") + except OSError: return False @@ -72,7 +71,6 @@ def checkout_latest_tag(local_repo: StrOrPath) -> str: def clone(url: str, ref: str = "HEAD") -> str: location = tempfile.mkdtemp(prefix=f"{__name__}.clone.") - shutil.rmtree(location) # Path must not exist git("clone", "--no-checkout", url, location) with local.cwd(location): git("checkout", ref) diff --git a/tests/demo_migrations/copier.yaml b/tests/demo_migrations/copier.yaml index 0e9211804..e363b8ba6 100644 --- a/tests/demo_migrations/copier.yaml +++ b/tests/demo_migrations/copier.yaml @@ -1,11 +1,11 @@ _exclude: - - tasks.sh + - tasks.py - migrations.py - .git _tasks: - - "[[ _copier_conf.src_path / 'tasks.sh' ]] 1" - - ["[[ _copier_conf.src_path / 'tasks.sh' ]]", 2] + - "python3 [[ _copier_conf.src_path / 'tasks.py' ]] 1" + - [python3, "[[ _copier_conf.src_path / 'tasks.py' ]]", 2] _migrations: # This migration is never executed because it's the 1st version copied, and diff --git a/tests/demo_migrations/tasks.py b/tests/demo_migrations/tasks.py new file mode 100755 index 000000000..74503badc --- /dev/null +++ b/tests/demo_migrations/tasks.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import os +import os.path +import sys +from contextlib import suppress + +from plumbum.cmd import git + +with open("created-with-tasks.txt", "a", newline="\n") as cwt: + cwt.write(" ".join([os.environ["STAGE"]] + sys.argv[1:]) + "\n") + git("init") + with suppress(FileNotFoundError): + os.unlink("delete-in-tasks.txt") diff --git a/tests/demo_migrations/tasks.sh b/tests/demo_migrations/tasks.sh deleted file mode 100755 index 50b26976b..000000000 --- a/tests/demo_migrations/tasks.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -echo $STAGE "$@" >> created-with-tasks.txt -git init -rm -f delete-in-tasks.txt diff --git a/tests/test_config.py b/tests/test_config.py index 1262d5016..705f729e6 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,4 +1,3 @@ -import re from pathlib import Path import pytest @@ -45,11 +44,12 @@ def test_read_data(tmp_path, template): def test_invalid_yaml(capsys): - conf_path = Path("tests/demo_invalid/copier.yml") + conf_path = Path("tests", "demo_invalid", "copier.yml") with pytest.raises(InvalidConfigFileError): load_yaml_data(conf_path) out, _ = capsys.readouterr() - assert re.search(r"INVALID.*tests/demo_invalid/copier\.yml", out) + assert "INVALID CONFIG FILE" in out + assert str(conf_path) in out @pytest.mark.parametrize( diff --git a/tests/test_migrations.py b/tests/test_migrations.py index 258315e89..f53936d1e 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -35,7 +35,7 @@ def test_migrations_and_tasks(tmpdir: py.path.local): assert not (tmp_path / "delete-in-tasks.txt").exists() assert (tmp_path / "delete-in-migration-v2.txt").isfile() assert not (tmp_path / "migrations.py").exists() - assert not (tmp_path / "tasks.sh").exists() + assert not (tmp_path / "tasks.py").exists() assert not glob(str(tmp_path / "*-before.txt")) assert not glob(str(tmp_path / "*-after.txt")) answers = yaml.safe_load((tmp_path / ".copier-answers.yml").read()) @@ -53,7 +53,7 @@ def test_migrations_and_tasks(tmpdir: py.path.local): assert not (tmp_path / "delete-in-tasks.txt").exists() assert not (tmp_path / "delete-in-migration-v2.txt").exists() assert not (tmp_path / "migrations.py").exists() - assert not (tmp_path / "tasks.sh").exists() + assert not (tmp_path / "tasks.py").exists() assert (tmp_path / "v1.0.0-v2-v2.0-before.json").isfile() assert (tmp_path / "v1.0.0-v2-v2.0-after.json").isfile() answers = yaml.safe_load((tmp_path / ".copier-answers.yml").read()) diff --git a/tests/test_vcs.py b/tests/test_vcs.py index 4af0d54bf..9d1776741 100644 --- a/tests/test_vcs.py +++ b/tests/test_vcs.py @@ -45,4 +45,4 @@ def test_clone(): tmp = vcs.clone("https://github.com/copier-org/copier.git") assert tmp assert exists(join(tmp, "README.md")) - shutil.rmtree(tmp) + shutil.rmtree(tmp, ignore_errors=True)