diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ae107e8..f309b5a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - id: check-yaml - id: detect-private-key - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.16.2" + rev: "v2.19.0" hooks: - id: pyproject-fmt - repo: https://github.com/citation-file-format/cffconvert @@ -17,7 +17,7 @@ repos: hooks: - id: validate-cff - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: v2.4.2 hooks: - id: codespell exclude: | @@ -39,7 +39,7 @@ repos: - id: yamllint exclude: pre-commit-config.yaml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.15.4" + rev: "v0.15.6" hooks: - id: ruff-format - id: ruff-check @@ -53,7 +53,7 @@ repos: - id: pre-commit-update args: ["--keep", "mdformat", "--keep", "pre-commit-update", "--keep", "cffconvert"] - repo: https://github.com/jendrikseipp/vulture - rev: 'v2.14' + rev: 'v2.15' hooks: - id: vulture - repo: https://github.com/aristanetworks/j2lint diff --git a/README.md b/README.md index fb77717..22a0a31 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Follow these steps to use this template: 1. Follow the directions in your new repo's `README.md` and make sure to check each file for alignment with your project. 1. Enjoy! +Copier already excludes `.git` from rendered output, so copying this template into an existing repository keeps that repository's history in place instead of importing this template's history. Copier also does not automatically run `git init` for a fresh destination. That could be done with a post-copy task, but Copier treats tasks as an unsafe feature, so this template leaves repository initialization as an explicit user step. + ## What's included in the template - Pre-configured `pyproject.toml` for Python project management diff --git a/copier.yaml b/copier.yaml index 3426374..63070b6 100644 --- a/copier.yaml +++ b/copier.yaml @@ -43,6 +43,12 @@ github_url: and other places. _exclude: + - .git + - .DS_Store + - .svn + - __pycache__ + - "*.py[co]" + - "~*" - copier.yaml - tests/test_template.py - .github/workflows/test-template.yml diff --git a/tests/test_template.py b/tests/test_template.py index fb623dc..4e16da4 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -8,6 +8,22 @@ from copier import run_copy +def _git(*args: str, cwd: Path) -> str: + return subprocess.check_output(["git", *args], cwd=cwd, text=True).strip() + + +def _init_git_repo(path: Path) -> str: + subprocess.run(["git", "init"], cwd=path, check=True) + subprocess.run(["git", "config", "user.name", "Test User"], cwd=path, check=True) + subprocess.run( + ["git", "config", "user.email", "test@example.com"], cwd=path, check=True + ) + (path / "README.md").write_text("# Existing repo\n") + subprocess.run(["git", "add", "README.md"], cwd=path, check=True) + subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=path, check=True) + return _git("rev-parse", "HEAD", cwd=path) + + def test_template(tmp_path: Path) -> None: # Path to the Copier template root template_path = Path(__file__).resolve().parent.parent @@ -33,6 +49,33 @@ def test_template(tmp_path: Path) -> None: # Assert a file from the template was created assert (dst_path / "src/demo_project/main.py").exists() + assert not (dst_path / ".git").exists() # Run pytest from the copied template subprocess.run(["uv", "run", "pytest"], cwd=dst_path, check=True) + + +def test_template_preserves_existing_git_repo(tmp_path: Path) -> None: + template_path = Path(__file__).resolve().parent.parent + dst_path = tmp_path / "existing-repo" + dst_path.mkdir() + original_head = _init_git_repo(dst_path) + + run_copy( + src_path=str(template_path), + dst_path=dst_path, + data={ + "project_name": "demo-project", + "project_description": "A demo project for testing Copier templates.", + "author_name": "Test Author", + "author_orcid": "https://orcid.org/0000-0000-0000-0000", + "github_url": "https://github.com/org/repo", + }, + quiet=True, + overwrite=True, + vcs_ref="HEAD", + ) + + assert (dst_path / "src/demo_project/main.py").exists() + assert _git("rev-parse", "--is-inside-work-tree", cwd=dst_path) == "true" + assert _git("rev-parse", "HEAD", cwd=dst_path) == original_head