Error handler for shutil.rmtree.

    Windows source repo folders are read-only by default, so this error handler
    attempts to set them as writeable and then proceed with deletion.

    :param function func: The caller function
    :param str path: The target path for removal
    :param Exception exc: The raised exception

    This function will call check :func:`is_readonly_path` before attempting to call
    :func:`set_write_bit` on the target path and try again.

def handle_remove_readonly(func, path, exc):
    """Error handler for shutil.rmtree.

    Windows source repo folders are read-only by default, so this error handler
    attempts to set them as writeable and then proceed with deletion.

    :param function func: The caller function
    :param str path: The target path for removal
    :param Exception exc: The raised exception

    This function will call check :func:`is_readonly_path` before attempting to call
    :func:`set_write_bit` on the target path and try again.
    """
    # Check for read-only attribute
    from .compat import ResourceWarning, FileNotFoundError, PermissionError

    PERM_ERRORS = (errno.EACCES, errno.EPERM, errno.ENOENT)
    default_warning_message = "Unable to remove file due to permissions restriction: {!r}"
    # split the initial exception out into its type, exception, and traceback
    exc_type, exc_exception, exc_tb = exc
    if is_readonly_path(path):
        # Apply write permission and call original function
        set_write_bit(path)
        try:
            func(path)
        except (OSError, IOError, FileNotFoundError, PermissionError) as e:
            if e.errno == errno.ENOENT:
                return
            elif e.errno in PERM_ERRORS:
                remaining = None
                if os.path.isdir(path):
                    remaining =_wait_for_files(path)
                if remaining:
                    warnings.warn(default_warning_message.format(path), ResourceWarning)
                return
            raise

    if exc_exception.errno in PERM_ERRORS:
        set_write_bit(path)
        remaining = _wait_for_files(path)
        try:
            func(path)
        except (OSError, IOError, FileNotFoundError, PermissionError) as e:
            if e.errno in PERM_ERRORS:
                warnings.warn(default_warning_message.format(path), ResourceWarning)
                pass
            elif e.errno == errno.ENOENT:  # File already gone
                pass
            else:
                raise
        else:
            return
    elif exc_exception.errno == errno.ENOENT:
        pass
    else:
        raise exc_exception