Skip to content

Commit

Permalink
Add workaround for cleaning out read-only files when wiping repo cont…
Browse files Browse the repository at this point in the history
…ext.

Closes #12
  • Loading branch information
jaraco committed Aug 19, 2024
1 parent e051242 commit 9c41698
Showing 1 changed file with 29 additions and 2 deletions.
31 changes: 29 additions & 2 deletions jaraco/context/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import annotations

import contextlib
import errno
import functools
import operator
import os
import platform
import shutil
import stat
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -133,6 +136,28 @@ def composed(*args, **kwargs):
"""


def remove_readonly(func, path, exc_info):
"""
Add support for removing read-only files on Windows.
"""
_, exc, _ = exc_info
if func in (os.rmdir, os.remove, os.unlink) and exc.errno == errno.EACCES:
# change the file to be readable,writable,executable: 0777
os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
# retry
func(path)
else:
raise


def robust_remover():
return (
functools.partial(shutil.rmtree, onerror=remove_readonly)
if platform.system() == 'Windows'
else shutil.rmtree
)


@contextlib.contextmanager
def temp_dir(remover: Callable[[str], None] = shutil.rmtree) -> Iterator[str]:
"""
Expand All @@ -142,7 +167,6 @@ def temp_dir(remover: Callable[[str], None] = shutil.rmtree) -> Iterator[str]:
>>> import pathlib
>>> with temp_dir() as the_dir:
... assert os.path.isdir(the_dir)
... _ = pathlib.Path(the_dir).joinpath('somefile').write_text('contents', encoding='utf-8')
>>> assert not os.path.exists(the_dir)
"""
temp_dir = tempfile.mkdtemp()
Expand All @@ -152,12 +176,15 @@ def temp_dir(remover: Callable[[str], None] = shutil.rmtree) -> Iterator[str]:
remover(temp_dir)


robust_temp_dir = functools.partial(temp_dir, remover=robust_remover())


@contextlib.contextmanager
def repo_context(
url,
branch: str | None = None,
quiet: bool = True,
dest_ctx: Callable[[], contextlib.AbstractContextManager[str]] = temp_dir,
dest_ctx: Callable[[], contextlib.AbstractContextManager[str]] = robust_temp_dir,
):
"""
Check out the repo indicated by url.
Expand Down

0 comments on commit 9c41698

Please sign in to comment.