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)