Skip to content
4 changes: 3 additions & 1 deletion copier/_vcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ def clone(url: str, ref: str | None = None) -> str:
)

with local.cwd(location):
git("checkout", "-f", ref or "HEAD")
## The `git checkout -f <ref>` command doesn't works when repo is local, dirty and core.fsmonitor is enabled
## ref: https://github.com/copier-org/copier/issues/1887
git("-c", "core.fsmonitor=false", "checkout", "-f", ref or "HEAD")
git("submodule", "update", "--checkout", "--init", "--recursive", "--force")

return location
Expand Down
32 changes: 30 additions & 2 deletions tests/test_vcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
import pytest
from packaging.version import Version
from plumbum import local
from pytest_gitconfig.plugin import GitConfig

from copier import run_copy, run_update
from copier._main import Worker
from copier._user_data import load_answersfile_data
from copier._vcs import checkout_latest_tag, clone, get_git_version, get_repo
from copier.errors import ShallowCloneWarning
from copier.errors import DirtyLocalWarning, ShallowCloneWarning

from .helpers import git
from .helpers import build_file_tree, git, git_save


def test_get_repo() -> None:
Expand Down Expand Up @@ -88,6 +89,33 @@ def test_local_clone() -> None:
shutil.rmtree(local_tmp, ignore_errors=True)


def test_local_dirty_clone(
tmp_path_factory: pytest.TempPathFactory, gitconfig: GitConfig
) -> None:
"""
When core.fsmonitor is enabled, normal `git checkout` command won't works.
"""

gitconfig.set({"core.fsmonitor": "true"})
src = tmp_path_factory.mktemp("src")
print(src)

build_file_tree({src / "version.txt": "0.1.0"})
git_save(src)

build_file_tree({src / "version.txt": "0.2.0", src / "README.md": "hello world"})

with pytest.warns(DirtyLocalWarning):
local_tmp = clone(str(src))

assert local_tmp
assert Path(local_tmp, "version.txt").exists()
assert Path(local_tmp, "version.txt").read_text() == "0.2.0"
assert Path(local_tmp, "README.md").exists()
assert Path(local_tmp, "README.md").read_text() == "hello world"
shutil.rmtree(local_tmp, ignore_errors=True)


@pytest.mark.impure
def test_shallow_clone(tmp_path: Path, recwarn: pytest.WarningsRecorder) -> None:
# This test should always work but should be much slower if `is_git_shallow_repo()` is not
Expand Down
Loading